From 7b9a819fed4c0041150476972e03b15b2fe47eb9 Mon Sep 17 00:00:00 2001
From: rswindell <>
Date: Wed, 10 Sep 2003 08:02:43 +0000
Subject: [PATCH] Created branch_t.gc_attempts (JS_MaybeGC call counter) and
 branch_t.terminated (pointer to server/service/host-process termination
 requested flag) so js.terminated should be used in place of server.terminated
 for universal scripts.

---
 src/sbbs3/exec.cpp      |  2 +-
 src/sbbs3/js_internal.c | 61 ++++++++++++++++++++++++++---------------
 src/sbbs3/jsexec.c      |  3 +-
 src/sbbs3/main.cpp      |  1 +
 src/sbbs3/sbbsdefs.h    |  2 ++
 src/sbbs3/services.c    |  4 ++-
 6 files changed, 48 insertions(+), 25 deletions(-)

diff --git a/src/sbbs3/exec.cpp b/src/sbbs3/exec.cpp
index 01d18f4f96..f01041c456 100644
--- a/src/sbbs3/exec.cpp
+++ b/src/sbbs3/exec.cpp
@@ -551,7 +551,7 @@ js_BranchCallback(JSContext *cx, JSScript *script)
 		YIELD();
 
 	if(sbbs->js_branch.gc_interval && (sbbs->js_branch.counter%sbbs->js_branch.gc_interval)==0)
-		JS_MaybeGC(cx);
+		JS_MaybeGC(cx), sbbs->js_branch.gc_attempts++;
 
     return(JS_TRUE);
 }
diff --git a/src/sbbs3/js_internal.c b/src/sbbs3/js_internal.c
index cc56687fc4..34239beb97 100644
--- a/src/sbbs3/js_internal.c
+++ b/src/sbbs3/js_internal.c
@@ -40,15 +40,17 @@
 #include <jscntxt.h>	/* Needed for Context-private data structure */
 
 enum {
-	 PROP_BRANCH_COUNTER
+	 PROP_TERMINATED
+	,PROP_BRANCH_COUNTER
 	,PROP_BRANCH_LIMIT
 	,PROP_YIELD_INTERVAL
 	,PROP_GC_INTERVAL
+	,PROP_GC_ATTEMPTS
 #ifdef jscntxt_h___
-	,PROP_GC_BYTES
-	,PROP_GC_LASTBYTES
-	,PROP_GC_MAXBYTES
 	,PROP_GC_COUNTER
+	,PROP_GC_LASTBYTES
+	,PROP_BYTES
+	,PROP_MAXBYTES
 #endif
 };
 
@@ -63,6 +65,10 @@ static JSBool js_get(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
     tiny = JSVAL_TO_INT(id);
 
 	switch(tiny) {
+		case PROP_TERMINATED:
+			if(branch->terminated!=NULL)
+				*vp=BOOLEAN_TO_JSVAL(*branch->terminated);
+			break;
 		case PROP_BRANCH_COUNTER:
 			JS_NewNumberValue(cx,branch->counter,vp);
 			break;
@@ -75,18 +81,21 @@ static JSBool js_get(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
 		case PROP_GC_INTERVAL:
 			JS_NewNumberValue(cx,branch->gc_interval,vp);
 			break;
+		case PROP_GC_ATTEMPTS:
+			JS_NewNumberValue(cx,branch->gc_attempts,vp);
+			break;
 #ifdef jscntxt_h___
-		case PROP_GC_BYTES:
-			JS_NewNumberValue(cx,cx->runtime->gcBytes,vp);
+		case PROP_GC_COUNTER:
+			JS_NewNumberValue(cx,cx->runtime->gcNumber,vp);
 			break;
 		case PROP_GC_LASTBYTES:
 			JS_NewNumberValue(cx,cx->runtime->gcLastBytes,vp);
 			break;
-		case PROP_GC_MAXBYTES:
-			JS_NewNumberValue(cx,cx->runtime->gcMaxBytes,vp);
+		case PROP_BYTES:
+			JS_NewNumberValue(cx,cx->runtime->gcBytes,vp);
 			break;
-		case PROP_GC_COUNTER:
-			JS_NewNumberValue(cx,cx->runtime->gcNumber,vp);
+		case PROP_MAXBYTES:
+			JS_NewNumberValue(cx,cx->runtime->gcMaxBytes,vp);
 			break;
 #endif
 	}
@@ -105,6 +114,10 @@ static JSBool js_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
     tiny = JSVAL_TO_INT(id);
 
 	switch(tiny) {
+		case PROP_TERMINATED:
+			if(branch->terminated!=NULL)
+				JS_ValueToBoolean(cx, *vp, branch->terminated);
+			break;
 		case PROP_BRANCH_COUNTER:
 			JS_ValueToInt32(cx, *vp, (int32*)&branch->counter);
 			break;
@@ -119,38 +132,42 @@ static JSBool js_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
 			break;
 	}
 
-	return(TRUE);
+	return(JS_TRUE);
 }
 
-#define GC_PROP_FLAGS	JSPROP_ENUMERATE|JSPROP_READONLY
+#define RT_PROP_FLAGS	JSPROP_ENUMERATE|JSPROP_READONLY
 
 static struct JSPropertySpec js_properties[] = {
 /*		 name,				tinyid,						flags,				getter,	setter	*/
 
+	{	"terminated",		PROP_TERMINATED,	JSPROP_ENUMERATE,	NULL,	NULL },
 	{	"branch_counter",	PROP_BRANCH_COUNTER,JSPROP_ENUMERATE,	NULL,	NULL },
 	{	"branch_limit",		PROP_BRANCH_LIMIT,	JSPROP_ENUMERATE,	NULL,	NULL },
 	{	"yield_interval",	PROP_YIELD_INTERVAL,JSPROP_ENUMERATE,	NULL,	NULL },
 	{	"gc_interval",		PROP_GC_INTERVAL,	JSPROP_ENUMERATE,	NULL,	NULL },
+	{	"gc_attempts",		PROP_GC_ATTEMPTS,	RT_PROP_FLAGS,		NULL,	NULL },
 #ifdef jscntxt_h___
-	{	"gc_bytes",			PROP_GC_BYTES,		GC_PROP_FLAGS,		NULL,	NULL },
-	{	"gc_last_bytes",	PROP_GC_LASTBYTES,	GC_PROP_FLAGS,		NULL,	NULL },
-	{	"gc_max_bytes",		PROP_GC_MAXBYTES,	GC_PROP_FLAGS,		NULL,	NULL },
-	{	"gc_counter",		PROP_GC_COUNTER,	GC_PROP_FLAGS,		NULL,	NULL },
+	{	"gc_counter",		PROP_GC_COUNTER,	RT_PROP_FLAGS,		NULL,	NULL },
+	{	"gc_last_bytes",	PROP_GC_LASTBYTES,	RT_PROP_FLAGS,		NULL,	NULL },
+	{	"bytes",			PROP_BYTES,			RT_PROP_FLAGS,		NULL,	NULL },
+	{	"max_bytes",		PROP_MAXBYTES,		RT_PROP_FLAGS,		NULL,	NULL },
 #endif
 	{0}
 };
 
 #ifdef _DEBUG
 static char* prop_desc[] = {
-	 "counter incremented for each branch"
+	 "termination has been requested (stop execution as soon as possible)"
+	,"number of branch operations performed in this runtime"
 	,"maximum number of branches, used for infinite-loop detection (0=disabled)"
-	,"interval of periodic garbage collection (lower number=higher frequency, 0=disabled)"
 	,"interval of periodic time-slice yields (lower number=higher frequency, 0=disabled)"
+	,"interval of periodic garbage collection attempts (lower number=higher frequency, 0=disabled)"
+	,"number of garbage collections attempted in this runtime"
 #ifdef jscntxt_h___
-	,"number of bytes currently in heap"
-	,"number of bytes in heap after last garbage collection"
-	,"maximum number of bytes in heap"
-	,"number of garbage collections"
+	,"number of garbage collections performed in this runtime"
+	,"number of heap bytes in use after last garbage collection"
+	,"number of heap bytes currently in use"
+	,"maximum number of bytes available for heap"
 #endif
 	,NULL
 };
diff --git a/src/sbbs3/jsexec.c b/src/sbbs3/jsexec.c
index 1f1c7c4962..2085acddb8 100644
--- a/src/sbbs3/jsexec.c
+++ b/src/sbbs3/jsexec.c
@@ -401,7 +401,7 @@ js_BranchCallback(JSContext *cx, JSScript *script)
 		YIELD();
 
 	if(branch.gc_interval && (branch.counter%branch.gc_interval)==0)
-		JS_MaybeGC(cx);
+		JS_MaybeGC(cx), branch.gc_attempts++;
 
 	if(terminated) {
 	
@@ -661,6 +661,7 @@ int main(int argc, char **argv, char** environ)
 	branch.limit=JAVASCRIPT_BRANCH_LIMIT;
 	branch.yield_interval=JAVASCRIPT_YIELD_INTERVAL;
 	branch.gc_interval=JAVASCRIPT_GC_INTERVAL;
+	branch.terminated=&terminated;
 
 	sscanf("$Revision$", "%*s %s", revision);
 
diff --git a/src/sbbs3/main.cpp b/src/sbbs3/main.cpp
index 4007751d53..b7e5b3e962 100644
--- a/src/sbbs3/main.cpp
+++ b/src/sbbs3/main.cpp
@@ -767,6 +767,7 @@ bool sbbs_t::js_init()
 	js_branch.gc_interval = JAVASCRIPT_GC_INTERVAL;
 	js_branch.yield_interval = JAVASCRIPT_YIELD_INTERVAL;
 	js_branch.counter = 0;	/* loop counter */
+	js_branch.terminated = (BOOL*)&terminated;
 
 	bool success=false;
 
diff --git a/src/sbbs3/sbbsdefs.h b/src/sbbs3/sbbsdefs.h
index d422934ac5..685ab67bc0 100644
--- a/src/sbbs3/sbbsdefs.h
+++ b/src/sbbs3/sbbsdefs.h
@@ -75,6 +75,8 @@ typedef struct {
 	ulong	limit;
 	ulong	yield_interval;
 	ulong	gc_interval;
+	ulong	gc_attempts;
+	BOOL*	terminated;
 } js_branch_t;
 
 #ifndef __FLAT__
diff --git a/src/sbbs3/services.c b/src/sbbs3/services.c
index c2ded1db4a..80646153b5 100644
--- a/src/sbbs3/services.c
+++ b/src/sbbs3/services.c
@@ -885,7 +885,7 @@ js_BranchCallback(JSContext *cx, JSScript *script)
 		YIELD();
 
 	if(client->branch.gc_interval && (client->branch.counter%client->branch.gc_interval)==0)
-		JS_MaybeGC(cx);
+		JS_MaybeGC(cx), client->branch.gc_attempts++;
 
     return(JS_TRUE);
 }
@@ -1135,6 +1135,7 @@ static void js_static_service_thread(void* arg)
 	service_client.branch.limit = JAVASCRIPT_BRANCH_LIMIT;
 	service_client.branch.gc_interval = JAVASCRIPT_GC_INTERVAL;
 	service_client.branch.yield_interval = JAVASCRIPT_YIELD_INTERVAL;
+	service_client.branch.terminated = &service->terminated;
 
 	if((js_runtime=JS_NewRuntime(startup->js_max_bytes))==NULL) {
 		lprintf("%04d !%s ERROR initializing JavaScript runtime"
@@ -2014,6 +2015,7 @@ void DLLCALL services_thread(void* arg)
 				client->branch.limit=JAVASCRIPT_BRANCH_LIMIT;
 				client->branch.gc_interval=JAVASCRIPT_GC_INTERVAL;
 				client->branch.yield_interval=JAVASCRIPT_YIELD_INTERVAL;
+				client->branch.terminated=&client->service->terminated;
 
 				udp_buf = NULL;
 
-- 
GitLab