diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 9fcdd542a797..3a6325f379c9 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -5632,7 +5632,7 @@ TraceRecorder::test_property_cache(JSObject* obj, LIns* obj_ins, JSObject*& obj2 // 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); @@ -7334,11 +7334,13 @@ TraceRecorder::record_JSOP_CALLNAME() 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))); @@ -7617,7 +7619,7 @@ TraceRecorder::name(jsval*& vp) 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"); @@ -7649,6 +7651,25 @@ TraceRecorder::prop(JSObject* obj, LIns* obj_ins, uint32& slot, LIns*& v_ins) /* 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); @@ -8187,6 +8208,10 @@ TraceRecorder::record_JSOP_BINDNAME() 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");