Unbox iterator after deep bail. Bug 618574, r=dvander.
☠☠ backed out by 123fa989ef70 ☠ ☠
authorJason Orendorff <jorendorff@mozilla.com>
Thu, 16 Dec 2010 14:59:50 -0800
changeset 59892 47a4f03b594711239602c567ed69887850cf21c7
parent 59891 41ff7f6d02d96ea03c06f0be1b75c6c307e87161
child 59893 dd1ae29025055882c4634c08c5ea35f0799ae362
push id17820
push usercleary@mozilla.com
push dateTue, 04 Jan 2011 21:40:57 +0000
treeherdermozilla-central@969691cfe40e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdvander
bugs618574
milestone2.0b8pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Unbox iterator after deep bail. Bug 618574, r=dvander.
js/src/jstracer.cpp
js/src/tests/js1_8_5/regress/regress-618574.js
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -7189,17 +7189,17 @@ TraceRecorder::monitorRecording(JSOp op)
         LIns* cond = pendingGuardCondition;
         bool expected = true;
         /* Put 'cond' in a form suitable for a guard/branch condition if it's not already. */
         ensureCond(&cond, &expected);
         guard(expected, cond, STATUS_EXIT);
         pendingGuardCondition = NULL;
     }
 
-    /* Handle one-shot request to unbox the result of a property get. */
+    /* Handle one-shot request to unbox the result of a property get or ObjectToIterator. */
     if (pendingUnboxSlot) {
         LIns* val_ins = get(pendingUnboxSlot);
         /*
          * We need to know from where to unbox the value. Since pendingUnboxSlot
          * is only set in finishGetProp, we can depend on LIns* tracked for
          * pendingUnboxSlot to have this information.
          */
         LIns* unboxed_ins = unbox_value(*pendingUnboxSlot,
@@ -14360,56 +14360,59 @@ TraceRecorder::record_JSOP_LOCALDEC()
 JS_REQUIRES_STACK AbortableRecordingStatus
 TraceRecorder::record_JSOP_IMACOP()
 {
     JS_ASSERT(cx->fp()->hasImacropc());
     return ARECORD_CONTINUE;
 }
 
 static JSBool FASTCALL
-ObjectToIterator(JSContext* cx, JSObject *obj, int32 flags, JSObject **objp)
-{
-    AutoValueRooter tvr(cx, ObjectValue(*obj));
-    bool ok = js_ValueToIterator(cx, flags, tvr.addr());
+ObjectToIterator(JSContext* cx, JSObject *obj, int32 flags, Value* vp)
+{
+    bool ok = js_ValueToIterator(cx, flags, vp);
     if (!ok) {
         SetBuiltinError(cx);
         return false;
     }
-    *objp = &tvr.value().toObject();
     return cx->tracerState->builtinStatus == 0;
 }
-JS_DEFINE_CALLINFO_4(static, BOOL_FAIL, ObjectToIterator, CONTEXT, OBJECT, INT32, OBJECTPTR,
+JS_DEFINE_CALLINFO_4(static, BOOL_FAIL, ObjectToIterator, CONTEXT, OBJECT, INT32, VALUEPTR,
                      0, ACCSET_STORE_ANY)
 
 JS_REQUIRES_STACK AbortableRecordingStatus
 TraceRecorder::record_JSOP_ITER()
 {
     Value& v = stackval(-1);
     if (v.isPrimitive())
         RETURN_STOP_A("for-in on a primitive value");
 
     RETURN_IF_XML_A(v);
 
     LIns *obj_ins = get(&v);
     jsuint flags = cx->regs->pc[1];
 
     enterDeepBailCall();
 
-    LIns* objp_ins = w.allocp(sizeof(JSObject*));
-    LIns* args[] = { objp_ins, w.immi(flags), obj_ins, cx_ins };
+    LIns* vp_ins = w.allocp(sizeof(Value));
+    LIns* args[] = { vp_ins, w.immi(flags), obj_ins, cx_ins };
     LIns* ok_ins = w.call(&ObjectToIterator_ci, args);
 
     // We need to guard on ok_ins, but this requires a snapshot of the state
     // after this op. monitorRecording will do it for us.
     pendingGuardCondition = ok_ins;
 
+    // ObjectToIterator can deep-bail without throwing, leaving a value of
+    // unknown type in *vp (it can be either a function or a non-function
+    // object). Use the same mechanism as finishGetProp to arrange for
+    // LeaveTree to deal with this value.
+    pendingUnboxSlot = cx->regs->sp - 1;
+    set(pendingUnboxSlot, w.name(w.lddAlloc(vp_ins), "iterval"));
+
     leaveDeepBailCall();
 
-    stack(-1, w.name(w.ldpAlloc(objp_ins), "iterobj"));
-
     return ARECORD_CONTINUE;
 }
 
 static JSBool FASTCALL
 IteratorMore(JSContext *cx, JSObject *iterobj, Value *vp)
 {
     if (!js_IteratorMore(cx, iterobj, vp)) {
         SetBuiltinError(cx);
new file mode 100644
--- /dev/null
+++ b/js/src/tests/js1_8_5/regress/regress-618574.js
@@ -0,0 +1,20 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ * Contributors: Gary Kwong and Jason Orendorff
+ */
+
+var x = Proxy.create({
+    iterate: function () {
+            function f(){}
+            f.next = function () { throw StopIteration; }
+            return f;
+        }
+    });
+
+for each (var e in [{}, {}, {}, {}, {}, {}, {}, {}, x]) {
+    for (var v in e)  // do not assert
+        ;
+}
+
+reportCompare(0, 0, 'ok');