From 6f69a357180a64ed1fc0b28774ca578b91896a28 Mon Sep 17 00:00:00 2001 From: Andreas Gal Date: Thu, 10 Jul 2008 13:24:49 -0700 Subject: [PATCH] Root all strings and objects first when unboxing. Then box values that might trigger the GC (doubles/ints). This probably needs some performance tuning over time. --- js/src/jstracer.cpp | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 8a340075c7f9..b07a243f3aa8 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -668,9 +668,8 @@ box_jsval(JSContext* cx, jsval& v, uint8 t, double* slot) if (JSDOUBLE_IS_INT(d, i)) goto store_int; store_double: - /* GC is not allowed to hit as we come out of the native frame. We have to teach - the GC how to scan native frames to avoid this race condition. */ - JS_ASSERT(cx->doubleFreeList != NULL); + /* Its safe to trigger the GC here since we rooted all strings/objects and all the + doubles we already processed. */ return js_NewDoubleInRootedValue(cx, d, &v); case JSVAL_STRING: v = STRING_TO_JSVAL(*(JSString**)slot); @@ -688,13 +687,15 @@ box_jsval(JSContext* cx, jsval& v, uint8 t, double* slot) /* Attempt to unbox the given JS frame into a native frame, checking along the way that the supplied typemap holds. */ static bool -unbox(JSStackFrame* entryFrame, JSStackFrame* currentFrame, uint8* m, double* native) +unbox(JSStackFrame* entryFrame, JSStackFrame* currentFrame, uint8* map, double* native) { verbose_only(printf("unbox native@%p ", native);) + double* np = native; + uint8* mp = map; FORALL_SLOTS_IN_PENDING_FRAMES(entryFrame, currentFrame, - if (vp && !unbox_jsval(*vp, *m, native)) + if (vp && !unbox_jsval(*vp, *mp, np)) return false; - ++m; ++native + ++mp; ++np; ); verbose_only(printf("\n");) return true; @@ -703,13 +704,26 @@ unbox(JSStackFrame* entryFrame, JSStackFrame* currentFrame, uint8* m, double* na /* Box the given native frame into a JS frame. This only fails due to a hard error (out of memory for example). */ static bool -box(JSContext* cx, JSStackFrame* entryFrame, JSStackFrame* currentFrame, uint8* m, double* native) +box(JSContext* cx, JSStackFrame* entryFrame, JSStackFrame* currentFrame, uint8* map, double* native) { verbose_only(printf("box native@%p ", native);) + double* np = native; + uint8* mp = map; + /* Root all string and object references first (we don't need to call the GC for this). */ FORALL_SLOTS_IN_PENDING_FRAMES(entryFrame, currentFrame, - if (vp && !box_jsval(cx, *vp, *m, native)) + if (vp && (*mp == JSVAL_STRING || *mp == JSVAL_OBJECT) && !box_jsval(cx, *vp, *mp, np)) return false; - ++m; ++native + ++mp; ++np + ); + /* Now do this again but this time for all values (properly quicker than actually checking + the type and excluding strings and objects). The GC might kick in when we store doubles, + but everything is rooted now (all strings/objects and all doubles we already boxed). */ + np = native; + mp = map; + FORALL_SLOTS_IN_PENDING_FRAMES(entryFrame, currentFrame, + if (vp && !box_jsval(cx, *vp, *mp, np)) + return false; + ++mp; ++np ); verbose_only(printf("\n");) return true;