Bug 621374. Fix denseArrayElement to follow its contract for holes. r=njn
authorBoris Zbarsky <bzbarsky@mit.edu>
Wed, 29 Dec 2010 16:44:47 -0800
changeset 59956 6f0a7cfb06d708d279846b963548adba20ed54ff
parent 59955 c2beef54a0042c2818c343c3966be3e5bda30cc4
child 59957 9d777ec391773fbf1e9f3ed1e4787b236e0ca47b
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)
reviewersnjn
bugs621374
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
Bug 621374. Fix denseArrayElement to follow its contract for holes. r=njn
js/src/jit-test/tests/basic/testIncElem3.js
js/src/jstracer.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/testIncElem3.js
@@ -0,0 +1,6 @@
+var arr;
+for (var j = 0; j < 2 * RUNLOOP; ++j ) {
+    arr = [,];
+    ++arr[0];
+}
+assertEq(isNaN(arr[0]), true);
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -13897,16 +13897,20 @@ TraceRecorder::propTail(JSObject* obj, L
         *slotp = slot;
         *v_insp = v_ins;
     }
     if (outp)
         set(outp, v_ins);
     return RECORD_CONTINUE;
 }
 
+/*
+ * When we end up with a hole, read it as undefined, and make sure to set
+ * addr_ins to null.
+ */
 JS_REQUIRES_STACK RecordingStatus
 TraceRecorder::denseArrayElement(Value& oval, Value& ival, Value*& vp, LIns*& v_ins,
                                  LIns*& addr_ins, VMSideExit* branchExit)
 {
     JS_ASSERT(oval.isObject() && ival.isInt32());
 
     JSObject* obj = &oval.toObject();
     LIns* obj_ins = get(&oval);
@@ -13925,17 +13929,16 @@ TraceRecorder::denseArrayElement(Value& 
     jsuint capacity = obj->getDenseArrayCapacity();
     bool within = (jsuint(idx) < capacity);
     if (!within) {
         /* If not idx < capacity, stay on trace (and read value as undefined). */
         guard(true, w.geui(idx_ins, capacity_ins), branchExit);
 
         CHECK_STATUS(guardPrototypeHasNoIndexedProperties(obj, obj_ins, snapshot(MISMATCH_EXIT)));
 
-        // Return undefined and indicate that we didn't actually read this (addr_ins).
         v_ins = w.immiUndefined();
         addr_ins = NULL;
         return RECORD_CONTINUE;
     }
 
     /* Guard that index is within capacity. */
     guard(true, w.name(w.ltui(idx_ins, capacity_ins), "inRange"), branchExit);
 
@@ -13944,16 +13947,17 @@ TraceRecorder::denseArrayElement(Value& 
 	JS_ASSERT(sizeof(Value) == 8); // The |3| in the following statement requires this.
     addr_ins = w.name(w.getDslotAddress(obj_ins, idx_ins), "elemp");
     v_ins = unbox_value(*vp, DSlotsAddress(addr_ins), branchExit);
 
     /* Don't let the hole value escape. Turn it into an undefined. */
     if (vp->isMagic()) {
         CHECK_STATUS(guardPrototypeHasNoIndexedProperties(obj, obj_ins, snapshot(MISMATCH_EXIT)));
         v_ins = w.immiUndefined();
+        addr_ins = NULL;
     }
     return RECORD_CONTINUE;
 }
 
 /* See comments in TypedArrayTemplate<double>::copyIndexToValue. */
 LIns *
 TraceRecorder::canonicalizeNaNs(LIns *dval_ins)
 {