Closed Bug 360612 Opened 13 years ago Closed 13 years ago

GC can leave GSN cache pointing to destroyed script

Categories

(Core :: JavaScript Engine, defect, P1)

defect

Tracking

()

RESOLVED FIXED
mozilla1.9alpha1

People

(Reporter: igor, Assigned: brendan)

References

Details

(Keywords: fixed1.8.1.1)

Attachments

(1 file, 4 obsolete files)

[ This is trunk-only regression and spin-off of bug 347306 comment 20].

The patch for bug 347306 contains:

> #ifdef JS_THREADSAFE
>     /*
>      * Set all thread local freelists to NULL. We may visit a thread's
>      * freelist more than once. To avoid redundant clearing we unroll the
>      * current thread's step.
>+     *
>+     * Also, in case a JSScript wrapped in an object was finalized, we clear
>+     * the acx->gsnCache.script pointer and finish the cache's hashtable.
>      */
>     memset(cx->thread->gcFreeLists, 0, sizeof cx->thread->gcFreeLists);
>     iter = NULL;
>     while ((acx = js_ContextIterator(rt, JS_FALSE, &iter)) != NULL) {
>         if (!acx->thread || acx->thread == cx->thread)
>             continue;
>         memset(acx->thread->gcFreeLists, 0, sizeof acx->thread->gcFreeLists);
>+        JS_CLEAR_GSN_CACHE(acx);
>     }
> #endif

If there are more JSContext associated with the current thread besides the current one with GSN cache, then the loop will leave the caches uncleared. Thus they may point to a destroyed JSScript instance.
Attached patch fix (obsolete) — Splinter Review
Assignee: general → brendan
Status: NEW → ASSIGNED
Attachment #246203 - Flags: review?(igor.bukanov)
Need this to land the patch for bug 357306 on the 1.8 branch, and for js1.7src.

/be
Blocks: js1.7src
Priority: -- → P1
Target Milestone: --- → mozilla1.9alpha
Comment on attachment 246203 [details] [diff] [review]
fix

>--- jsgc.c	27 Oct 2006 19:38:33 -0000	3.180
>+++ jsgc.c	21 Nov 2006 21:50:36 -0000
>@@ -2819,19 +2819,23 @@ js_GC(JSContext *cx, JSGCInvocationKind 
> #endif
> 
> #ifdef JS_THREADSAFE
>     /*
>      * Set all thread local freelists to NULL. We may visit a thread's
>      * freelist more than once. To avoid redundant clearing we unroll the
>      * current thread's step.
>      *
>-     * Also, in case a JSScript wrapped in an object was finalized, we clear
>-     * the acx->gsnCache.script pointer and finish the cache's hashtable.
>+     * Also, in case a JSScript wrapped within an object was finalized, we
>+     * null acx->thread->gsnCache.script and finish the cache's hashtable.
>+     * Note that js_DestroyScript, called from script_finalize, will have
>+     * already cleared cx->thread->gsnCache above during finalization, so we
>+     * don't have to here.
>      */
>+    JS_ASSERT(!cx->thread->gsnCache.script);
>     memset(cx->thread->gcFreeLists, 0, sizeof cx->thread->gcFreeLists);
>     iter = NULL;
>     while ((acx = js_ContextIterator(rt, JS_FALSE, &iter)) != NULL) {
>         if (!acx->thread || acx->thread == cx->thread)
>             continue;
>         memset(acx->thread->gcFreeLists, 0, sizeof acx->thread->gcFreeLists);
>         JS_CLEAR_GSN_CACHE(acx);
>     }

This does not cover single-threaded case. For a minimal patch why not just move the cache nullifier code into the general context marking loop in js_GC and just do it there when acx != cx ?
Attachment #246203 - Flags: review?(igor.bukanov) → review-
Good idea -- also, the patch for bug 361451 provokes the question: why sweep atoms before objects, rather than after (as property tree nodes and script filenames are done)?

/be
Attached patch fix, v2 (obsolete) — Splinter Review
mrbkap, please feel free to review too.

/be
Attachment #246338 - Flags: review?(igor.bukanov)
Comment on attachment 246338 [details] [diff] [review]
fix, v2

Whoops, wrong bug.

/be
Attachment #246338 - Attachment is obsolete: true
Attachment #246338 - Flags: review?(igor.bukanov)
Attached patch fix, v2 (obsolete) — Splinter Review
Attachment #246203 - Attachment is obsolete: true
Attachment #246342 - Flags: review?(igor.bukanov)
Comment on attachment 246342 [details] [diff] [review]
fix, v2

>+#else
>+    /*
>+     * The thread-unsafe case just has to clear each context's GSN cache,
>+     * except for cx's of course (see previous comment).
>+     */
>+    while ((acx = js_ContextIterator(rt, JS_FALSE, &iter)) != NULL) {
>+        if (acx == cx)
>+            continue;
>+        JS_CLEAR_GSN_CACHE(acx);
>+    }
> #endif

This is very different behaviour between single and multi threaded cases. Why not to store the cache in the runtime when JS_THREADSAFE is not defined?
Attached patch fix, v3 (obsolete) — Splinter Review
Hope the single-threaded fill/hit-repeatedly-on-one-thread pattern is the common case, with no cache thrashing among contexts.

/be
Attachment #246342 - Attachment is obsolete: true
Attachment #246417 - Flags: review?(igor.bukanov)
Attachment #246342 - Flags: review?(igor.bukanov)
Attachment #246417 - Flags: review?(igor.bukanov) → review+
Fixed on trunk:

Checking in jscntxt.h;
/cvsroot/mozilla/js/src/jscntxt.h,v  <--  jscntxt.h
new revision: 3.127; previous revision: 3.126
done
Checking in jsgc.c;
/cvsroot/mozilla/js/src/jsgc.c,v  <--  jsgc.c
new revision: 3.184; previous revision: 3.183
done
Checking in jsscript.c;
/cvsroot/mozilla/js/src/jsscript.c,v  <--  jsscript.c
new revision: 3.122; previous revision: 3.121
done

/be
Status: ASSIGNED → RESOLVED
Closed: 13 years ago
Resolution: --- → FIXED
This patch seems to have caused the current tinderbox orange.
The stack to the crash and assertion failures that I see locally with that patch applied are at http://pastebin.mozilla.org/1539.
Backed out, completely botched the initialization of JSThread.gsnCache.  Revised patch soon.

/be
Status: RESOLVED → REOPENED
Resolution: FIXED → ---
Status: REOPENED → ASSIGNED
Attached patch fix, v4Splinter Review
Sorry for the blunder -- this works in my Firefox build.

/be
Attachment #246417 - Attachment is obsolete: true
Attachment #246451 - Flags: review?(igor.bukanov)
Attachment #246451 - Flags: review?(igor.bukanov) → review+
Checking in jsapi.c;
/cvsroot/mozilla/js/src/jsapi.c,v  <--  jsapi.c
new revision: 3.290; previous revision: 3.289
done
Checking in jscntxt.c;
/cvsroot/mozilla/js/src/jscntxt.c,v  <--  jscntxt.c
new revision: 3.94; previous revision: 3.93
done
Checking in jscntxt.h;
/cvsroot/mozilla/js/src/jscntxt.h,v  <--  jscntxt.h
new revision: 3.129; previous revision: 3.128
done
Checking in jsgc.c;
/cvsroot/mozilla/js/src/jsgc.c,v  <--  jsgc.c
new revision: 3.187; previous revision: 3.186
done
Checking in jsscript.c;
/cvsroot/mozilla/js/src/jsscript.c,v  <--  jsscript.c
new revision: 3.124; previous revision: 3.123
done

/be
Status: ASSIGNED → RESOLVED
Closed: 13 years ago13 years ago
Resolution: --- → FIXED
Flags: in-testsuite-
Blocks: 347306
No longer depends on: 347306
blocking 1.8.1.1 because it's a regression from a 1.8.1.1-blocking bug (for verification testing purposes).
No longer blocks: 347306
Depends on: 347306
Flags: blocking1.8.1.1+
Blocks: 347306
No longer depends on: 347306
Keywords: fixed1.8.1.1
You need to log in before you can comment on or make changes to this bug.