shithub: libmujs

Download patch

ref: b4297c0dec103a40bc1fc12792610d053fdd2bff
parent: 40b73014d9b41c48f689b80605ce5c9c37fa71cc
author: Tor Andersson <tor.andersson@artifex.com>
date: Wed Jul 25 07:58:28 EDT 2018

Fix 699557: Pause garbage collector during Ap_sort.

The temporary array we use for sorting cannot be seen by the GC, and that
violates the constraint that all js_Value values must always be reachable
from the stack or global environment.

Temporarily turning off the GC will let us use the temporary array for
fast sorting using qsort(), without tripping over this violation.

--- a/jsarray.c
+++ b/jsarray.c
@@ -300,7 +300,15 @@
 		js_rangeerror(J, "array is too large to sort");
 
 	array = js_malloc(J, len * sizeof *array);
+
+	/* Holding objects where the GC cannot see them is illegal, but if we
+	 * don't allow the GC to run we can use qsort() on a temporary array of
+	 * js_Values for fast sorting.
+	 */
+	++J->gcpause;
+
 	if (js_try(J)) {
+		--J->gcpause;
 		js_free(J, array);
 		js_throw(J);
 	}
@@ -324,6 +332,8 @@
 	for (i = n; i < len; ++i) {
 		js_delindex(J, 0, i);
 	}
+
+	--J->gcpause;
 
 	js_endtry(J);
 	js_free(J, array);
--- a/jsgc.c
+++ b/jsgc.c
@@ -129,6 +129,14 @@
 	int mark;
 	int i;
 
+	if (J->gcpause) {
+		if (report)
+			js_report(J, "garbage collector is paused");
+		return;
+	}
+
+	J->gccounter = 0;
+
 	mark = J->gcmark = J->gcmark == 1 ? 2 : 1;
 
 	jsG_markobject(J, mark, J->Object_prototype);
--- a/jsi.h
+++ b/jsi.h
@@ -214,6 +214,7 @@
 	js_Value *stack;
 
 	/* garbage collector list */
+	int gcpause;
 	int gcmark;
 	int gccounter;
 	js_Environment *gcenv;
--- a/jsrun.c
+++ b/jsrun.c
@@ -1303,10 +1303,8 @@
 	J->strict = F->strict;
 
 	while (1) {
-		if (J->gccounter > JS_GCLIMIT) {
-			J->gccounter = 0;
+		if (J->gccounter > JS_GCLIMIT)
 			js_gc(J, 0);
-		}
 
 		opcode = *pc++;
 		switch (opcode) {