Closed Bug 389832 Opened 17 years ago Closed 17 years ago

ActionMonkey: Remove GCF_LOCK flag, Eager init gcLocksHash

Categories

(Core :: JavaScript Engine, defect)

Other Branch
defect
Not set
normal

Tracking

()

RESOLVED FIXED

People

(Reporter: jorendorff, Assigned: Mardak)

References

Details

Attachments

(1 file, 2 obsolete files)

This is another small chunk of GC-related work that can be done before making the leap to MMgc allocation. Remove the GCF_LOCK flag from MMgc entirely. "Locked" objects are already stored in a hash table; simply modify jsgc.cpp to make sure all those objects are marked from js_TraceRuntime. Mark the empty string and special jsdoubles, too.
Sorry, I meant "Remove the GCF_LOCK flag from *SpiderMonkey* entirely" of course, not MMgc. Ed, can you take a look at this? You will also have to modify js_LockGCThingRT(), where it says: > /* > * Avoid adding a rt->gcLocksHash entry for shallow things until someone > * nests a lock -- then start such an entry with a count of 2, not 1. > */ > if (lock || deep) { This can no longer be avoided; the body of the if statement must happen unconditionally (bug 389420 comment 22). Don't waste a lot of time on it if it's not the right thing to do. It just occurred to me this is possible.
Assignee: general → edilee
(In reply to comment #0) > [...] "Locked" objects are already > stored in a hash table; simply modify jsgc.cpp to make sure all those objects > are marked from js_TraceRuntime. [...] Oops. That's a no-op -- js_TraceRuntime already does this. > if (rt->gcLocksHash) > JS_DHashTableEnumerate(rt->gcLocksHash, gc_lock_traversal, trc);
Attached patch v1 (obsolete) — Splinter Review
- Removed GCF_LOCK from jsgc, jsnum, jsstr. - Simplified js_(Lock|Unlock)GCThingRT to always add to the hash table (don't check if it's shallow) -- this also means various sanity checks for singly-locked shallow items aren't needed - Manually mark the constants from js_TraceRuntime for now, this will be removed when switching to MMgc (check null because they can disappear before the last GC)
Attachment #274212 - Flags: review?(jorendorff)
Comment on attachment 274212 [details] [diff] [review] v1 > void > js_TraceRuntime(JSTracer *trc, JSBool allAtoms) > { > JSRuntime *rt = trc->context->runtime; > JSContext *iter, *acx; > >+ /* >+ * Temporary hack to manually mark constants that are pointed by the >+ * JSRuntime. Eventually when switching to MMgc, the JSRuntime will >+ * automatically be scanned and mark these constants. >+ */ >+ if (rt->jsNaN) >+ *js_GetGCThingFlags(rt->jsNaN) |= GCF_MARK; >+ if (rt->jsNegativeInfinity) >+ *js_GetGCThingFlags(rt->jsNegativeInfinity) |= GCF_MARK; >+ if (rt->jsPositiveInfinity) >+ *js_GetGCThingFlags(rt->jsPositiveInfinity) |= GCF_MARK; >+ if (rt->emptyString) >+ *js_GetGCThingFlags(rt->emptyString) |= GCF_MARK; >+ This is wrong. Use JS_TRACE_DOUBLE/JS_TRACE_STRING here as tracing can happen without any GC activity. >diff -r f3f3535e5b4e js/src/jsnum.cpp >--- a/js/src/jsstr.cpp Thu Jul 26 17:24:46 2007 -0400 >+++ b/js/src/jsstr.cpp Fri Jul 27 14:30:52 2007 -0700 >@@ -2349,17 +2349,17 @@ js_InitRuntimeStringState(JSContext *cx) > JS_ASSERT(!rt->deflatedStringCacheLock); > rt->deflatedStringCacheLock = JS_NEW_LOCK(); > if (!rt->deflatedStringCacheLock) > return JS_FALSE; > #endif > > /* Make a permanently locked empty string. */ > JS_ASSERT(!rt->emptyString); >- empty = js_NewStringCopyN(cx, js_empty_ucstr, 0, GCF_LOCK); >+ empty = js_NewStringCopyN(cx, js_empty_ucstr, 0, 0); > if (!empty) > goto bad; This collides with my patch for bug 389880. Hopefully hg will do the right thing here.
Comment on attachment 274212 [details] [diff] [review] v1 > void > js_TraceRuntime(JSTracer *trc, JSBool allAtoms) > { ... >+ if (rt->emptyString) >+ *js_GetGCThingFlags(rt->emptyString) |= GCF_MARK; >+ This is not necessary. rt->emptyString is marked when pinned atoms are marked in jsatom.c. Thus only the numbers should be traced.
Attached patch v2 (obsolete) — Splinter Review
(In reply to comment #4) > >+ if (rt->jsNaN) > >+ *js_GetGCThingFlags(rt->jsNaN) |= GCF_MARK; > This is wrong. Use JS_TRACE_DOUBLE/JS_TRACE_STRING here as tracing can happen > without any GC activity. Fixed by using JS_CALL_DOUBLE_TRACER and JS_CALL_STRING_TRACER. (In reply to comment #5) > >+ if (rt->emptyString) > >+ *js_GetGCThingFlags(rt->emptyString) |= GCF_MARK; > This is not necessary. rt->emptyString is marked when pinned atoms are marked > in jsatom.c. Thus only the numbers should be traced. Removed.
Attachment #274218 - Flags: review?(igor)
Attachment #274212 - Attachment is obsolete: true
Attachment #274212 - Flags: review?(jorendorff)
> JSBool > js_UnlockGCThingRT(JSRuntime *rt, void *thing) It looks like with v1, rt->gcPoke is set unconditionally in js_UnlockGCThingRT(). Before, the poke was skipped if the lock count was still >0 after decrementing it.
Comment on attachment 274218 [details] [diff] [review] v2 > JSBool > js_UnlockGCThingRT(JSRuntime *rt, void *thing) > { >- uint8 *flagp, flags; > JSGCLockHashEntry *lhe; > > if (!thing) > return JS_TRUE; > >- flagp = js_GetGCThingFlags(thing); > JS_LOCK_GC(rt); >- flags = *flagp; >- >- if (flags & GCF_LOCK) { >- if (!rt->gcLocksHash || >- (lhe = (JSGCLockHashEntry *) >- JS_DHashTableOperate(rt->gcLocksHash, thing, >- JS_DHASH_LOOKUP), >- JS_DHASH_ENTRY_IS_FREE(&lhe->hdr))) { >- /* Shallow GC-thing with an implicit lock count of 1. */ >- JS_ASSERT(!GC_THING_IS_DEEP(flags & GCF_TYPEMASK, thing)); >- } else { >- /* Basis or nested unlock of a deep thing, or nested of shallow. */ >- if (--lhe->count != 0) >- goto out; >+ >+ if (rt->gcLocksHash) { >+ lhe = (JSGCLockHashEntry *) JS_DHashTableOperate(rt->gcLocksHash, thing, >+ JS_DHASH_LOOKUP); >+ if (--lhe->count == 0) The current version of js_UnlockGCThingRT allows to pass unlocked thing and does nothing in this case. To preserve the behavior for API compatibility it is necessary to check for non-null lhe here. r+ with this addressed.
Comment on attachment 274218 [details] [diff] [review] v2 (In reply to comment #7) > It looks like with v1, rt->gcPoke is set unconditionally in > js_UnlockGCThingRT(). Before, the poke was skipped if the lock count was still > >0 after decrementing it. Ah right. I moved it out earlier when I had it inside the first if.. Poke if.. 1) LOCK is set but wasn't put in the table (1 lock) 2) in the table but now removed I might as well just *not* lazily init gcLocksHash in the patch.
Attachment #274218 - Flags: review?(igor)
(In reply to comment #8) > The current version of js_UnlockGCThingRT allows to pass unlocked thing and > does nothing in this case. To preserve the behavior for API compatibility it is > necessary to check for non-null lhe here. r+ with this addressed. Of cause the check should not do lhe !+ null but rather those JS_DHASH_ENTRY_IS_FREE checks.
(In reply to comment #9) > I might as well just *not* lazily init gcLocksHash in the patch. That is a nice idea.
Attached patch v3Splinter Review
(In reply to comment #7) > Before, the poke was skipped if the lock count was still > >0 after decrementing it. Poked only on removal. (In reply to comment #11) > > I might as well just *not* lazily init gcLocksHash in the patch. > That is a nice idea. Un-lazy-ified. Saves on some null checks for every lock/unlock. (And no more gotos!) (In reply to comment #10) > > The current version of js_UnlockGCThingRT allows to pass unlocked thing and > > does nothing in this case. > Of course the check should not do lhe != null but rather those > JS_DHASH_ENTRY_IS_FREE checks. Checked. brendan: Now that gcLocksHash isn't lazily inited and will hold all locked items (minus constants), it'll grow in size faster than before. 1) JSRuntime has 2 of these DHashTable structs near the beginning (instead of 1 struct, 1 pointer) 2) we're reusing #define GC_ROOTS_SIZE 256 for initial capacity for locks <ibukanov> Then lets move both hashes towards the end of JSRuntime. <ibukanov> This is to avoid code bloat with 2 bytes offset for more frequently accessed fields. <ibukanov> But OK, I can file a separated bug about it. <ibukanov> As it would help CVS tip as well. Both those issues aren't critical right now for the current stage, but something to note for later. jorendorff: With gcLocksHash not lazily created, it'll be Alloced as part of GCRoot, so it'll save a step later on. We'll still need to modify the Ops to not use the StubOps and have them GC::Alloc instead. r? again for making not lazy.
Attachment #274218 - Attachment is obsolete: true
Attachment #274233 - Flags: review?(jorendorff)
Attachment #274233 - Flags: review?(igor)
Blocks: 387012
Status: NEW → ASSIGNED
Summary: ActionMonkey: remove GCF_LOCK flag → ActionMonkey: Remove GCF_LOCK flag, Eager init gcLocksHash
Attachment #274233 - Flags: review?(igor) → review+
I filed bug 389907 against SpiderMonkey to optimize JSRuntime layout.
(In reply to comment #12) > jorendorff: With gcLocksHash not lazily created, it'll be Alloced as part of > GCRoot, so it'll save a step later on. We'll still need to modify the Ops to > not use the StubOps and have them GC::Alloc instead. I said this a while ago, but we don't *have* to change this. It wouldn't save code, and it wouldn't run faster.
Attachment #274233 - Flags: review?(jorendorff) → review+
pushed to hg/actionmonkey remote: added 1 changesets with 5 changes to 5 files changeset 3736: 1d81f62e7970
Status: ASSIGNED → RESOLVED
Closed: 17 years ago
Resolution: --- → FIXED
Flags: in-testsuite-
Blocks: 392883
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: