Bug 462021 - TM: Make JSStackFrame reconstitution infallible (part 1 of 4, easy stuff, r=gal)
authorJason Orendorff <jorendorff@mozilla.com>
Thu, 11 Dec 2008 17:53:04 -0600
changeset 22922 df576b0261cd1336043ca4a9f0db404044f471d0
parent 22921 8280c2b9bbf9d43d874a33ba06c93c65d6446d3e
child 22923 df26ea871309999b86d423fa0c1a9567a0dfcc2a
push id500
push userrsayre@mozilla.com
push dateFri, 23 Jan 2009 04:05:55 +0000
reviewersgal
bugs462021
milestone1.9.1b3pre
Bug 462021 - TM: Make JSStackFrame reconstitution infallible (part 1 of 4, easy stuff, r=gal)
js/src/jstracer.cpp
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -1353,17 +1353,17 @@ oom:
      */
     tm->recoveryDoublePoolPtr = tm->recoveryDoublePool;
     return false;
 }
 
 /* Box a value from the native stack back into the jsval format. Integers
    that are too large to fit into a jsval are automatically boxed into
    heap-allocated doubles. */
-static bool
+static void
 NativeToValue(JSContext* cx, jsval& v, uint8 type, double* slot)
 {
     jsint i;
     jsdouble d;
     switch (type) {
       case JSVAL_BOOLEAN:
         v = BOOLEAN_TO_JSVAL(*(JSBool*)slot);
         debug_only_v(printf("boolean<%d> ", *(JSBool*)slot);)
@@ -1387,22 +1387,22 @@ NativeToValue(JSContext* cx, jsval& v, u
         /* Its not safe to trigger the GC here, so use an emergency heap if we are out of
            double boxes. */
         if (cx->doubleFreeList) {
 #ifdef DEBUG
             bool ok =
 #endif
                 js_NewDoubleInRootedValue(cx, d, &v);
             JS_ASSERT(ok);
-            return true;
+            return;
         }
         v = AllocateDoubleFromRecoveryPool(cx);
         JS_ASSERT(JSVAL_IS_DOUBLE(v) && *JSVAL_TO_DOUBLE(v) == 0.0);
         *JSVAL_TO_DOUBLE(v) = d;
-        return true;
+        return;
       }
       case JSVAL_STRING:
         v = STRING_TO_JSVAL(*(JSString**)slot);
         JS_ASSERT(JSVAL_TAG(v) == JSVAL_STRING); /* if this fails the pointer was not aligned */
         debug_only_v(printf("string<%p> ", *(JSString**)slot);)
         break;
       case JSVAL_BOXED:
         v = *(jsval*)slot;
@@ -1418,17 +1418,16 @@ NativeToValue(JSContext* cx, jsval& v, u
         v = OBJECT_TO_JSVAL(*(JSObject**)slot);
         JS_ASSERT(JSVAL_TAG(v) == JSVAL_OBJECT); /* if this fails the pointer was not aligned */
         debug_only_v(printf("object<%p:%s> ", JSVAL_TO_OBJECT(v),
                             JSVAL_IS_NULL(v)
                             ? "null"
                             : STOBJ_GET_CLASS(JSVAL_TO_OBJECT(v))->name);)
         break;
     }
-    return true;
 }
 
 /* Attempt to unbox the given list of interned globals onto the native global frame. */
 static JS_REQUIRES_STACK void
 BuildNativeGlobalFrame(JSContext* cx, unsigned ngslots, uint16* gslots, uint8* mp, double* np)
 {
     debug_only_v(printf("global: ");)
     FORALL_GLOBAL_SLOTS(cx, ngslots, gslots,
@@ -1446,34 +1445,32 @@ BuildNativeStackFrame(JSContext* cx, uns
     FORALL_SLOTS_IN_PENDING_FRAMES(cx, callDepth,
         debug_only_v(printf("%s%u=", vpname, vpnum);)
         ValueToNative(cx, *vp, *mp, np);
         ++mp; ++np;
     );
     debug_only_v(printf("\n");)
 }
 
-/* Box the given native frame into a JS frame. This only fails due to a hard error
-   (out of memory for example). */
+/* Box the given native frame into a JS frame. This is infallible. */
 static JS_REQUIRES_STACK int
 FlushNativeGlobalFrame(JSContext* cx, unsigned ngslots, uint16* gslots, uint8* mp, double* np)
 {
     uint8* mp_base = mp;
     FORALL_GLOBAL_SLOTS(cx, ngslots, gslots,
-        if (!NativeToValue(cx, *vp, *mp, np + gslots[n]))
-            return -1;
+        NativeToValue(cx, *vp, *mp, np + gslots[n]);
         ++mp;
     );
     debug_only_v(printf("\n");)
     return mp - mp_base;
 }
 
 /**
- * Box the given native stack frame into the virtual machine stack. This fails
- * only due to a hard error (out of memory for example).
+ * Box the given native stack frame into the virtual machine stack. This
+ * is infallible.
  *
  * @param callDepth the distance between the entry frame into our trace and
  *                  cx->fp when we make this call.  If this is not called as a
  *                  result of a nested exit, callDepth is 0.
  * @param mp pointer to an array of type tags (JSVAL_INT, etc.) that indicate
  *           what the types of the things on the stack are.
  * @param np pointer to the native stack.  We want to copy values from here to
  *           the JS stack as needed.
@@ -1486,18 +1483,17 @@ FlushNativeStackFrame(JSContext* cx, uns
                       JSStackFrame* stopFrame)
 {
     jsval* stopAt = stopFrame ? &stopFrame->argv[-2] : NULL;
     uint8* mp_base = mp;
     /* Root all string and object references first (we don't need to call the GC for this). */
     FORALL_SLOTS_IN_PENDING_FRAMES(cx, callDepth,
         if (vp == stopAt) goto skip;
         debug_only_v(printf("%s%u=", vpname, vpnum);)
-        if (!NativeToValue(cx, *vp, *mp, np))
-            return -1;
+        NativeToValue(cx, *vp, *mp, np);
         ++mp; ++np
     );
 skip:
     // Restore thisp from the now-restored argv[-1] in each pending frame.
     // Keep in mind that we didn't restore frames at stopFrame and above!
     // Scope to keep |fp| from leaking into the macros we're using.
     {
         unsigned n = callDepth+1; // +1 to make sure we restore the entry frame
@@ -2832,17 +2828,17 @@ js_SynthesizeFrame(JSContext* cx, const 
     if (a->avail + nbytes <= a->limit) {
         newsp = (jsval *) a->avail;
         a->avail += nbytes;
         JS_ASSERT(missing == 0);
     } else {
         JS_ARENA_ALLOCATE_CAST(newsp, jsval *, &cx->stackPool, nbytes);
         if (!newsp) {
             js_ReportOutOfScriptQuota(cx);
-            return 0;
+            return -1;
         }
 
         /*
          * Move args if the missing ones overflow arena a, then push
          * undefined for the missing args.
          */
         if (missing) {
             memcpy(newsp, vp, (2 + argc) * sizeof(jsval));
@@ -3638,19 +3634,17 @@ js_ExecuteTree(JSContext* cx, Fragment* 
         int slots = FlushNativeStackFrame(cx, 1/*callDepth*/, (uint8*)(*callstack+1), stack, cx->fp);
 #ifdef DEBUG
         JSStackFrame* fp = cx->fp;
         debug_only_v(printf("synthesized deep frame for %s:%u@%u, slots=%d\n",
                             fp->script->filename,
                             js_FramePCToLineNumber(cx, fp),
                             FramePCOffset(fp),
                             slots);)
-#endif        
-        if (slots < 0)
-            return NULL;
+#endif
         /* Keep track of the additional frames we put on the interpreter stack and the native
            stack slots we consumed. */
         ++inlineCallCount;
         ++callstack;
         stack += slots;
     }
 
     /* We already synthesized the frames around the innermost guard. Here we just deal
@@ -3716,28 +3710,27 @@ js_ExecuteTree(JSContext* cx, Fragment* 
     JS_ASSERT(ngslots >= exit_gslots);
     uint8* globalTypeMap = getTypeMap(innermost);
     if (exit_gslots < ngslots)
         mergeTypeMaps(&globalTypeMap, &exit_gslots, tm->globalTypeMap->data(), ngslots,
                       (uint8*)alloca(sizeof(uint8) * ngslots));
     JS_ASSERT(exit_gslots == tm->globalTypeMap->length());
 
     /* write back interned globals */
-    int slots = FlushNativeGlobalFrame(cx, exit_gslots, gslots, globalTypeMap, global);
-    if (slots < 0)
-        return NULL;
+    FlushNativeGlobalFrame(cx, exit_gslots, gslots, globalTypeMap, global);
     JS_ASSERT_IF(ngslots != 0, globalFrameSize == STOBJ_NSLOTS(globalObj));
     JS_ASSERT(*(uint64*)&global[globalFrameSize] == 0xdeadbeefdeadbeefLL);
 
     /* write back native stack frame */
-    slots = FlushNativeStackFrame(cx, innermost->calldepth,
-                                  getTypeMap(innermost) + innermost->numGlobalSlots,
-                                  stack, NULL);
-    if (slots < 0)
-        return NULL;
+#ifdef DEBUG
+    int slots =
+#endif
+        FlushNativeStackFrame(cx, innermost->calldepth,
+                              getTypeMap(innermost) + innermost->numGlobalSlots,
+                              stack, NULL);
     JS_ASSERT(unsigned(slots) == innermost->numStackSlots);
 
 #ifdef DEBUG
     // Verify that our state restoration worked
     for (JSStackFrame* fp = cx->fp; fp; fp = fp->down) {
         JS_ASSERT(!fp->callee || JSVAL_IS_OBJECT(fp->argv[-1]));
         JS_ASSERT(!fp->callee || fp->thisp == JSVAL_TO_OBJECT(fp->argv[-1]));
     }