Trace reading undefined properties (478512, r=brendan).
☠☠ backed out by 34ee950622aa ☠ ☠
authorAndreas Gal <gal@mozilla.com>
Thu, 19 Feb 2009 19:41:03 -0800
changeset 25470 a2b6a4c57a0557c922bef92bc96c388441192384
parent 25469 86c57e08cfe78ef5572620563f56ea3857a73b14
child 25471 34ee950622aa5c2f92b3143421fee9eef6952c5a
push id5575
push userrsayre@mozilla.com
push dateWed, 25 Feb 2009 09:05:38 +0000
treeherdermozilla-central@8eba35e62d92 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbrendan
bugs478512
milestone1.9.2a1pre
Trace reading undefined properties (478512, r=brendan).
js/src/jstracer.cpp
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -5627,17 +5627,17 @@ TraceRecorder::test_property_cache(JSObj
         if (!prop) {
             // Propagate obj from js_FindPropertyHelper to record_JSOP_BINDNAME
             // via our obj2 out-parameter. If we are recording JSOP_SETNAME and
             // the global it's assigning does not yet exist, create it.
             obj2 = obj;
 
             // Use PCVAL_NULL to return "no such property" to our caller.
             pcval = PCVAL_NULL;
-            ABORT_TRACE("failed to find property");
+            return true;
         }
 
         OBJ_DROP_PROPERTY(cx, obj2, prop);
         if (!entry)
             ABORT_TRACE("failed to fill property cache");
     }
 
     if (wasDeepAborted())
@@ -7329,21 +7329,23 @@ TraceRecorder::record_JSOP_CALLNAME()
         stack(0, get(vp));
         stack(1, globalObj_ins);
         return true;
     }
 
     LIns* obj_ins = scopeChain();
     JSObject* obj2;
     jsuword pcval;
+
     if (!test_property_cache(obj, obj_ins, obj2, pcval))
         return false;
 
     if (PCVAL_IS_NULL(pcval) || !PCVAL_IS_OBJECT(pcval))
         ABORT_TRACE("callee is not an object");
+
     JS_ASSERT(HAS_FUNCTION_CLASS(PCVAL_TO_OBJECT(pcval)));
 
     stack(0, INS_CONSTPTR(PCVAL_TO_OBJECT(pcval)));
     stack(1, obj_ins);
     return true;
 }
 
 JS_REQUIRES_STACK bool
@@ -7612,17 +7614,17 @@ TraceRecorder::name(jsval*& vp)
 
     /* Can't use prop here, because we don't want unboxing from global slots. */
     LIns* obj_ins = scopeChain();
     uint32 slot;
     if (!test_property_cache_direct_slot(obj, obj_ins, slot))
         return false;
 
     if (slot == SPROP_INVALID_SLOT)
-        ABORT_TRACE("name op can't find named property");
+        ABORT_TRACE("named property not found");
 
     if (!lazilyImportGlobalSlot(slot))
         ABORT_TRACE("lazy import of global slot failed");
 
     vp = &STOBJ_GET_SLOT(obj, slot);
     return true;
 }
 
@@ -7644,16 +7646,35 @@ TraceRecorder::prop(JSObject* obj, LIns*
     JSObject* obj2;
     jsuword pcval;
     if (!test_property_cache(obj, obj_ins, obj2, pcval))
         return false;
 
     /* Check for non-existent property reference, which results in undefined. */
     const JSCodeSpec& cs = js_CodeSpec[*cx->fp->regs->pc];
     if (PCVAL_IS_NULL(pcval)) {
+        /*
+         * This trace will be valid as long as neither the object nor any object
+         * on its prototype chain change shape.
+         */
+        while ((obj2 = JSVAL_TO_OBJECT(obj->fslots[JSSLOT_PROTO])) = NULL) {
+            LIns* obj2_ins = stobj_get_fslot(obj_ins, JSSLOT_PROTO);
+            LIns* map_ins = lir->insLoad(LIR_ldp, obj2_ins, (int)offsetof(JSObject, map));
+            LIns* ops_ins;
+            if (!map_is_native(obj2->map, map_ins, ops_ins))
+                ABORT_TRACE("non-native object along prototype chain");
+
+            LIns* shape_ins = addName(lir->insLoad(LIR_ld, map_ins, offsetof(JSScope, shape)),
+                                      "shape");
+            guard(true,
+                  addName(lir->ins2i(LIR_eq, shape_ins, OBJ_SHAPE(obj2)), "guard(shape)"),
+                  BRANCH_EXIT);
+            obj = obj2;
+            obj_ins = obj2_ins;
+        }
         v_ins = INS_CONST(JSVAL_TO_PSEUDO_BOOLEAN(JSVAL_VOID));
         JS_ASSERT(cs.ndefs == 1);
         stack(-cs.nuses, v_ins);
         slot = SPROP_INVALID_SLOT;
         return true;
     }
 
     /* Insist if setting on obj being the directly addressed object. */
@@ -8182,16 +8203,20 @@ TraceRecorder::record_JSOP_BINDNAME()
     if (obj != globalObj)
         ABORT_TRACE("JSOP_BINDNAME crosses global scopes");
 
     LIns* obj_ins = scopeChain();
     JSObject* obj2;
     jsuword pcval;
     if (!test_property_cache(obj, obj_ins, obj2, pcval))
         return false;
+    
+    if (PCVAL_IS_NULL(pcval))
+        ABORT_TRACE("JSOP_BINDNAME is trying to add a new property");
+    
     if (obj2 != obj)
         ABORT_TRACE("JSOP_BINDNAME found a non-direct property on the global object");
 
     stack(0, obj_ins);
     return true;
 }
 
 JS_REQUIRES_STACK bool