TM: Assertion failure: isInt32(*p), r=gal, approval1.9.1.1=beltzner.
authorDavid Anderson <danderson@mozilla.com>
Tue, 14 Jul 2009 14:45:28 -0700
changeset 26063 315a381a0bb58b91f0422106b1695a04314cf6b9
parent 26062 f3031a3f5fc62f30b8bdef41767bd4f74ff253d6
child 26064 9d3a32d9ef1ea4a434aafca90e809130489515ff
push id1770
push usergraydon@mozilla.com
push dateTue, 14 Jul 2009 21:46:52 +0000
reviewersgal
milestone1.9.1.1pre
TM: Assertion failure: isInt32(*p), r=gal, approval1.9.1.1=beltzner.
js/src/jstracer.cpp
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -3275,16 +3275,29 @@ TraceRecorder::emitTreeCall(Fragment* in
     LIns* args[] = { INS_CONSTPTR(inner), lirbuf->state }; /* reverse order */
     LIns* ret = lir->insCall(&js_CallTree_ci, args);
 
     /* Read back all registers, in case the called tree changed any of them. */
     JS_ASSERT(!memchr(getGlobalTypeMap(exit), JSVAL_BOXED, exit->numGlobalSlots) &&
               !memchr(getStackTypeMap(exit), JSVAL_BOXED, exit->numStackSlots));
     import(ti, inner_sp_ins, exit->numStackSlots, exit->numGlobalSlots,
            exit->calldepth, getFullTypeMap(exit));
+    /* bug 502604 - It is illegal to extend from the outer typemap without first extending from the
+     * inner. Make a new typemap here.
+     */
+    TypeMap fullMap;
+    fullMap.add(getStackTypeMap(exit), exit->numStackSlots);
+    fullMap.add(getGlobalTypeMap(exit), exit->numGlobalSlots);
+    TreeInfo* innerTree = (TreeInfo*)exit->from->root->vmprivate;
+    if (exit->numGlobalSlots < innerTree->nGlobalTypes()) {
+        fullMap.add(innerTree->globalTypeMap() + exit->numGlobalSlots,
+                    innerTree->nGlobalTypes() - exit->numGlobalSlots);
+    }
+    import(ti, inner_sp_ins, exit->numStackSlots, fullMap.length() - exit->numStackSlots,
+           exit->calldepth, fullMap.data());
 
     /* Restore sp and rp to their original values (we still have them in a register). */
     if (callDepth > 0) {
         lir->insStorei(lirbuf->sp, lirbuf->state, offsetof(InterpState, sp));
         lir->insStorei(lirbuf->rp, lirbuf->state, offsetof(InterpState, rp));
     }
 
     /*
@@ -4075,19 +4088,41 @@ js_AttemptToExtendTree(JSContext* cx, VM
                and the actual guard we exited from has the types for everything in the current
                scope (and whatever it inlined). We have to merge those maps here. */
             VMSideExit* e1 = anchor;
             VMSideExit* e2 = exitedFrom;
             fullMap.add(getStackTypeMap(e1), e1->numStackSlotsBelowCurrentFrame);
             fullMap.add(getStackTypeMap(e2), e2->numStackSlots);
             stackSlots = fullMap.length();
             fullMap.add(getGlobalTypeMap(e2), e2->numGlobalSlots);
-            if (e1->numGlobalSlots >= e2->numGlobalSlots) {
-                fullMap.add(getGlobalTypeMap(e1) + e2->numGlobalSlots,
-                            e1->numGlobalSlots - e2->numGlobalSlots);
+            if (e2->numGlobalSlots < e1->numGlobalSlots) {
+                /* Watch out for an extremely rare case (bug 502714). The sequence of events is:
+                 * 
+                 * 1) Inner tree compiles not knowing about global X (which has type A).
+                 * 2) Inner tree learns about global X and specializes it to a different type
+                 *    (type B).
+                 * 3) Outer tree records inner tree with global X as type A, exiting as B.
+                 * 4) Outer tree now has a nesting guard with typeof(X)=B.
+                 * 5) Inner tree takes its original exit that does not know about X.
+                 * 
+                 * In this case, the nesting guard fails, and now it is illegal to use the nested
+                 * typemap entry for X. The correct entry is in the inner guard's TreeInfo,
+                 * analogous to the solution for bug 476653.
+                 */
+                TreeInfo* innerTree = (TreeInfo*)e2->from->root->vmprivate;
+                unsigned slots = e2->numGlobalSlots;
+                if (innerTree->nGlobalTypes() > slots) {
+                    unsigned addSlots = JS_MIN(innerTree->nGlobalTypes() - slots,
+                                               e1->numGlobalSlots - slots);
+                    fullMap.add(innerTree->globalTypeMap() + e2->numGlobalSlots, addSlots);
+                    slots += addSlots;
+                }
+                if (slots < e1->numGlobalSlots)
+                    fullMap.add(getGlobalTypeMap(e1) + slots, e1->numGlobalSlots - slots);
+                JS_ASSERT(slots == e1->numGlobalSlots);
             }
             ngslots = e1->numGlobalSlots;
             typeMap = fullMap.data();
         }
         JS_ASSERT(ngslots >= anchor->numGlobalSlots);
         return js_StartRecorder(cx, anchor, c, (TreeInfo*)f->vmprivate, stackSlots,
                                 ngslots, typeMap, exitedFrom, outer, cx->fp->argc);
     }