From 99424f7beb6b795729ea495330e4fa58759b703b Mon Sep 17 00:00:00 2001 From: Andreas Gal Date: Thu, 13 Aug 2009 04:08:34 -0700 Subject: [PATCH] Backed out bug 508051. Fails trace-test/mandelbrot. --- js/src/imacros.c.out | 74 +++++++++- js/src/imacros.jsasm | 63 ++++++++ js/src/jstracer.cpp | 336 +++++++++++++++++++------------------------ js/src/jstracer.h | 7 - js/src/trace-test.js | 30 ---- 5 files changed, 282 insertions(+), 228 deletions(-) diff --git a/js/src/imacros.c.out b/js/src/imacros.c.out index cafb21981382..907d038dcfc4 100644 --- a/js/src/imacros.c.out +++ b/js/src/imacros.c.out @@ -627,6 +627,66 @@ static struct { /*11*/ JSOP_STOP, }, }; +static struct { + jsbytecode setprop[15]; + jsbytecode setelem[15]; +} setelem_imacros = { + { +/* 0*/ JSOP_DUP, +/* 1*/ JSOP_PICK, 3, +/* 3*/ JSOP_CALLBUILTIN, ((JSBUILTIN_SetProperty) & 0xff00) >> 8, ((JSBUILTIN_SetProperty) & 0xff), +/* 6*/ JSOP_PICK, 4, +/* 8*/ JSOP_PICK, 4, +/*10*/ JSOP_CALL, 0, 2, +/*13*/ JSOP_POP, +/*14*/ JSOP_STOP, + }, + { +/* 0*/ JSOP_DUP, +/* 1*/ JSOP_PICK, 3, +/* 3*/ JSOP_CALLBUILTIN, ((JSBUILTIN_SetElement) & 0xff00) >> 8, ((JSBUILTIN_SetElement) & 0xff), +/* 6*/ JSOP_PICK, 4, +/* 8*/ JSOP_PICK, 4, +/*10*/ JSOP_CALL, 0, 2, +/*13*/ JSOP_POP, +/*14*/ JSOP_STOP, + }, +}; +static struct { + jsbytecode initprop[15]; + jsbytecode initelem[15]; +} initelem_imacros = { + { +/* 0*/ JSOP_PICK, 2, +/* 2*/ JSOP_DUP, +/* 3*/ JSOP_CALLBUILTIN, ((JSBUILTIN_SetProperty) & 0xff00) >> 8, ((JSBUILTIN_SetProperty) & 0xff), +/* 6*/ JSOP_PICK, 4, +/* 8*/ JSOP_PICK, 4, +/*10*/ JSOP_CALL, 0, 2, +/*13*/ JSOP_POP, +/*14*/ JSOP_STOP, + }, + { +/* 0*/ JSOP_PICK, 2, +/* 2*/ JSOP_DUP, +/* 3*/ JSOP_CALLBUILTIN, ((JSBUILTIN_SetElement) & 0xff00) >> 8, ((JSBUILTIN_SetElement) & 0xff), +/* 6*/ JSOP_PICK, 4, +/* 8*/ JSOP_PICK, 4, +/*10*/ JSOP_CALL, 0, 2, +/*13*/ JSOP_POP, +/*14*/ JSOP_STOP, + }, +}; +static struct { + jsbytecode instanceof[9]; +} instanceof_imacros = { + { +/* 0*/ JSOP_CALLBUILTIN, ((JSBUILTIN_HasInstance) & 0xff00) >> 8, ((JSBUILTIN_HasInstance) & 0xff), +/* 3*/ JSOP_PICK, 2, +/* 5*/ JSOP_CALL, 0, 1, +/* 8*/ JSOP_STOP, + }, +}; uint8 js_opcode2extra[JSOP_LIMIT] = { 0, /* JSOP_NOP */ 0, /* JSOP_PUSH */ @@ -684,7 +744,7 @@ uint8 js_opcode2extra[JSOP_LIMIT] = { 0, /* JSOP_GETPROP */ 0, /* JSOP_SETPROP */ 0, /* JSOP_GETELEM */ - 0, /* JSOP_SETELEM */ + 2, /* JSOP_SETELEM */ 0, /* JSOP_CALLNAME */ 3, /* JSOP_CALL */ 0, /* JSOP_NAME */ @@ -720,7 +780,7 @@ uint8 js_opcode2extra[JSOP_LIMIT] = { 0, /* JSOP_NEWINIT */ 0, /* JSOP_ENDINIT */ 0, /* JSOP_INITPROP */ - 0, /* JSOP_INITELEM */ + 2, /* JSOP_INITELEM */ 0, /* JSOP_DEFSHARP */ 0, /* JSOP_USESHARP */ 0, /* JSOP_INCARG */ @@ -740,7 +800,7 @@ uint8 js_opcode2extra[JSOP_LIMIT] = { 0, /* JSOP_SETNAME */ 0, /* JSOP_THROW */ 0, /* JSOP_IN */ - 0, /* JSOP_INSTANCEOF */ + 1, /* JSOP_INSTANCEOF */ 0, /* JSOP_DEBUGGER */ 0, /* JSOP_GOSUB */ 0, /* JSOP_RETSUB */ @@ -883,11 +943,14 @@ uint8 js_opcode2extra[JSOP_LIMIT] = { || x == JSOP_MOD \ || x == JSOP_NEG \ || x == JSOP_POS \ + || x == JSOP_SETELEM \ || x == JSOP_CALL \ || x == JSOP_ITER \ || x == JSOP_NEXTITER \ || x == JSOP_APPLY \ || x == JSOP_NEW \ + || x == JSOP_INITELEM \ + || x == JSOP_INSTANCEOF \ ) jsbytecode* js_GetImacroStart(jsbytecode* pc) { @@ -926,5 +989,10 @@ js_GetImacroStart(jsbytecode* pc) { if (size_t(pc - iter_imacros.for_each_native) < 10) return iter_imacros.for_each_native; if (size_t(pc - nextiter_imacros.custom_iter_next) < 12) return nextiter_imacros.custom_iter_next; if (size_t(pc - nextiter_imacros.native_iter_next) < 12) return nextiter_imacros.native_iter_next; + if (size_t(pc - setelem_imacros.setprop) < 15) return setelem_imacros.setprop; + if (size_t(pc - setelem_imacros.setelem) < 15) return setelem_imacros.setelem; + if (size_t(pc - initelem_imacros.initprop) < 15) return initelem_imacros.initprop; + if (size_t(pc - initelem_imacros.initelem) < 15) return initelem_imacros.initelem; + if (size_t(pc - instanceof_imacros.instanceof) < 9) return instanceof_imacros.instanceof; return NULL; } diff --git a/js/src/imacros.jsasm b/js/src/imacros.jsasm index 790dac1736f5..4463a8675902 100644 --- a/js/src/imacros.jsasm +++ b/js/src/imacros.jsasm @@ -672,3 +672,66 @@ .end .end nextiter + +.igroup setelem JSOP_SETELEM + + .imacro setprop # obj name val + dup # obj name val val + pick 3 # name val val obj + callbuiltin (JSBUILTIN_SetProperty) # name val val fun obj + pick 4 # val val fun obj name + pick 4 # val fun obj name val + call 2 # val junk + pop # val + stop + .end + + .imacro setelem # obj i val + dup # obj i val val + pick 3 # i val val obj + callbuiltin (JSBUILTIN_SetElement) # i val val fun obj + pick 4 # val val fun obj i + pick 4 # val fun obj i val + call 2 # val junk + pop # val + stop + .end + +.end setelem + +.igroup initelem JSOP_INITELEM + + .imacro initprop # obj i val + pick 2 # i val obj + dup # i val obj obj + callbuiltin (JSBUILTIN_SetProperty) # i val obj fun obj + pick 4 # val obj fun obj i + pick 4 # obj fun obj i val + call 2 # obj junk + pop # obj + stop + .end + + .imacro initelem # obj i val + pick 2 # i val obj + dup # i val obj obj + callbuiltin (JSBUILTIN_SetElement) # i val obj fun obj + pick 4 # val obj fun obj i + pick 4 # obj fun obj i val + call 2 # obj junk + pop # obj + stop + .end + +.end initelem + +.igroup instanceof JSOP_INSTANCEOF + + .imacro instanceof # val obj + callbuiltin (JSBUILTIN_HasInstance) # val fun obj + pick 2 # fun obj val + call 1 # bool + stop + .end + +.end instanceof diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index d0841c8e8d21..fc8c5d85fc2d 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -5562,9 +5562,7 @@ LeaveTree(InterpState& state, VMSideExit* lr) JSOp op = (JSOp) *regs->pc; JS_ASSERT(op == JSOP_CALL || op == JSOP_APPLY || op == JSOP_NEW || op == JSOP_GETELEM || op == JSOP_CALLELEM || - op == JSOP_SETPROP || op == JSOP_SETNAME || - op == JSOP_SETELEM || op == JSOP_INITELEM || - op == JSOP_INSTANCEOF); + op == JSOP_SETPROP || op == JSOP_SETNAME); const JSCodeSpec& cs = js_CodeSpec[op]; regs->sp -= (cs.format & JOF_INVOKE) ? GET_ARGC(regs->pc) + 2 : cs.nuses; regs->sp += cs.ndefs; @@ -9881,66 +9879,53 @@ TraceRecorder::finishGetProp(LIns* obj_ins, LIns* vp_ins, LIns* ok_ins, jsval* o pendingUnboxSlot = outp; } -static inline bool -RootedStringToId(JSContext* cx, JSString** namep, jsid* idp) -{ - JSString* name = *namep; - if (name->isAtomized()) { - *idp = ATOM_TO_JSID((JSAtom*) STRING_TO_JSVAL(name)); - return true; - } - - JSAtom* atom = js_AtomizeString(cx, name, 0); - if (!atom) - return false; - *namep = ATOM_TO_STRING(atom); /* write back to GC root */ - *idp = ATOM_TO_JSID(atom); - return true; -} - static JSBool FASTCALL GetPropertyByName(JSContext* cx, JSObject* obj, JSString** namep, jsval* vp) { js_LeaveTraceIfGlobalObject(cx, obj); jsid id; - if (!RootedStringToId(cx, namep, &id) || !obj->getProperty(cx, id, vp)) { - js_SetBuiltinError(cx); - return JS_FALSE; + JSString* name = *namep; + if (name->isAtomized()) { + id = ATOM_TO_JSID((JSAtom*) STRING_TO_JSVAL(name)); + } else { + JSAtom* atom = js_AtomizeString(cx, name, 0); + if (!atom) + goto error; + *namep = ATOM_TO_STRING(atom); /* write back to GC root */ + id = ATOM_TO_JSID(atom); } + + if (!obj->getProperty(cx, id, vp)) + goto error; return cx->interpState->builtinStatus == 0; + +error: + js_SetBuiltinError(cx); + return JS_FALSE; } JS_DEFINE_CALLINFO_4(static, BOOL_FAIL, GetPropertyByName, CONTEXT, OBJECT, STRINGPTR, JSVALPTR, 0, 0) -// Convert the value in a slot to a string and store the resulting string back -// in the slot (typically in order to root it). -JS_REQUIRES_STACK JSRecordingStatus -TraceRecorder::primitiveToStringInPlace(jsval* vp) -{ - jsval v = *vp; - JS_ASSERT(JSVAL_IS_PRIMITIVE(v)); - - if (!JSVAL_IS_STRING(v)) { - // v is not a string. Turn it into one. js_ValueToString is safe - // because v is not an object. - JSString *str = js_ValueToString(cx, v); - if (!str) - ABORT_TRACE_ERROR("failed to stringify element id"); - v = STRING_TO_JSVAL(str); - set(vp, stringify(*vp)); - - // Write the string back to the stack to save the interpreter some work - // and to ensure snapshots get the correct type for this slot. - *vp = v; - } - return JSRS_CONTINUE; -} - JS_REQUIRES_STACK JSRecordingStatus TraceRecorder::getPropertyByName(LIns* obj_ins, jsval* idvalp, jsval* outp) { - CHECK_STATUS(primitiveToStringInPlace(idvalp)); + jsval idval = *idvalp; + JS_ASSERT(JSVAL_IS_PRIMITIVE(idval)); + + if (!JSVAL_IS_STRING(idval)) { + // idval is not a string. Turn it into one. + // js_ValueToString is a safe because idval is not an object. + JSString *str = js_ValueToString(cx, idval); + if (!str) + ABORT_TRACE_ERROR("failed to stringify element id"); + idval = STRING_TO_JSVAL(str); + set(idvalp, stringify(*idvalp)); + + // Write the string back to the stack to save the interpreter some work. + *idvalp = idval; + } + enterDeepBailCall(); // Call GetPropertyByName. The vp parameter points to stack because this is @@ -10121,120 +10106,72 @@ TraceRecorder::record_JSOP_GETELEM() /* Functions used by JSOP_SETELEM */ -static JSBool FASTCALL -SetPropertyByName(JSContext* cx, JSObject* obj, JSString** namep, jsval* vp) +static JSBool +SetProperty(JSContext *cx, uintN argc, jsval *vp) { - js_LeaveTraceIfGlobalObject(cx, obj); - + jsval *argv; jsid id; - if (!RootedStringToId(cx, namep, &id) || !obj->setProperty(cx, id, vp)) { - js_SetBuiltinError(cx); + + JS_ASSERT(argc == 2); + argv = JS_ARGV(cx, vp); + JS_ASSERT(JSVAL_IS_STRING(argv[0])); + if (!js_ValueToStringId(cx, argv[0], &id)) return JS_FALSE; - } - return cx->interpState->builtinStatus == 0; + argv[0] = ID_TO_VALUE(id); + if (!JS_THIS_OBJECT(cx, vp)->setProperty(cx, id, &argv[1])) + return JS_FALSE; + JS_SET_RVAL(cx, vp, JSVAL_VOID); + return JS_TRUE; } -JS_DEFINE_CALLINFO_4(static, BOOL_FAIL, SetPropertyByName, CONTEXT, OBJECT, STRINGPTR, JSVALPTR, - 0, 0) static JSBool FASTCALL -InitPropertyByName(JSContext* cx, JSObject* obj, JSString** namep, jsval val) +SetProperty_tn(JSContext* cx, JSObject* obj, JSString* idstr, jsval v) { - js_LeaveTraceIfGlobalObject(cx, obj); + JSAutoTempValueRooter tvr(cx, v); + JSAutoTempIdRooter idr(cx); + if (!js_ValueToStringId(cx, STRING_TO_JSVAL(idstr), idr.addr()) || + !obj->setProperty(cx, idr.id(), tvr.addr())) { + js_SetBuiltinError(cx); + } + return JSVAL_TO_SPECIAL(JSVAL_VOID); +} + +static JSBool +SetElement(JSContext *cx, uintN argc, jsval *vp) +{ + jsval *argv; jsid id; - if (!RootedStringToId(cx, namep, &id) || - !obj->defineProperty(cx, id, val, NULL, NULL, JSPROP_ENUMERATE, NULL)) { - js_SetBuiltinError(cx); + + JS_ASSERT(argc == 2); + argv = JS_ARGV(cx, vp); + JS_ASSERT(JSVAL_IS_NUMBER(argv[0])); + if (!JS_ValueToId(cx, argv[0], &id)) return JS_FALSE; - } - return cx->interpState->builtinStatus == 0; -} -JS_DEFINE_CALLINFO_4(static, BOOL_FAIL, InitPropertyByName, CONTEXT, OBJECT, STRINGPTR, JSVAL, - 0, 0) - -JS_REQUIRES_STACK JSRecordingStatus -TraceRecorder::initOrSetPropertyByName(LIns* obj_ins, jsval* idvalp, jsval* rvalp, bool init) -{ - CHECK_STATUS(primitiveToStringInPlace(idvalp)); - - LIns* rval_ins = get(rvalp); - box_jsval(*rvalp, rval_ins); - - enterDeepBailCall(); - - LIns* ok_ins; - LIns* idvalp_ins = addName(addr(idvalp), "idvalp"); - if (init) { - LIns* args[] = {rval_ins, idvalp_ins, obj_ins, cx_ins}; - ok_ins = lir->insCall(&InitPropertyByName_ci, args); - } else { - // See note in getPropertyByName about vp. - LIns* vp_ins = addName(lir->insAlloc(sizeof(jsval)), "vp"); - lir->insStorei(rval_ins, vp_ins, 0); - LIns* args[] = {vp_ins, idvalp_ins, obj_ins, cx_ins}; - ok_ins = lir->insCall(&SetPropertyByName_ci, args); - } - guard(true, ok_ins, STATUS_EXIT); - - leaveDeepBailCall(); - return JSRS_CONTINUE; + argv[0] = ID_TO_VALUE(id); + if (!JS_THIS_OBJECT(cx, vp)->setProperty(cx, id, &argv[1])) + return JS_FALSE; + JS_SET_RVAL(cx, vp, JSVAL_VOID); + return JS_TRUE; } static JSBool FASTCALL -SetPropertyByIndex(JSContext* cx, JSObject* obj, int32 index, jsval* vp) +SetElement_tn(JSContext* cx, JSObject* obj, int32 index, jsval v) { - js_LeaveTraceIfGlobalObject(cx, obj); - JSAutoTempIdRooter idr(cx); - if (!js_Int32ToId(cx, index, idr.addr()) || !obj->setProperty(cx, idr.id(), vp)) { - js_SetBuiltinError(cx); - return JS_FALSE; - } - return cx->interpState->builtinStatus == 0; -} -JS_DEFINE_CALLINFO_4(static, BOOL_FAIL, SetPropertyByIndex, CONTEXT, OBJECT, INT32, JSVALPTR, 0, 0) + JSAutoTempValueRooter tvr(cx, v); -static JSBool FASTCALL -InitPropertyByIndex(JSContext* cx, JSObject* obj, int32 index, jsval val) -{ - js_LeaveTraceIfGlobalObject(cx, obj); - - JSAutoTempIdRooter idr(cx); if (!js_Int32ToId(cx, index, idr.addr()) || - !obj->defineProperty(cx, idr.id(), val, NULL, NULL, JSPROP_ENUMERATE, NULL)) { + !obj->setProperty(cx, idr.id(), tvr.addr())) { js_SetBuiltinError(cx); - return JS_FALSE; } - return cx->interpState->builtinStatus == 0; + return JSVAL_TO_SPECIAL(JSVAL_VOID); } -JS_DEFINE_CALLINFO_4(static, BOOL_FAIL, InitPropertyByIndex, CONTEXT, OBJECT, INT32, JSVAL, 0, 0) -JS_REQUIRES_STACK JSRecordingStatus -TraceRecorder::initOrSetPropertyByIndex(LIns* obj_ins, LIns* index_ins, jsval* rvalp, bool init) -{ - index_ins = makeNumberInt32(index_ins); - - LIns* rval_ins = get(rvalp); - box_jsval(*rvalp, rval_ins); - - enterDeepBailCall(); - - LIns* ok_ins; - if (init) { - LIns* args[] = {rval_ins, index_ins, obj_ins, cx_ins}; - ok_ins = lir->insCall(&InitPropertyByIndex_ci, args); - } else { - // See note in getPropertyByName about vp. - LIns* vp_ins = addName(lir->insAlloc(sizeof(jsval)), "vp"); - lir->insStorei(rval_ins, vp_ins, 0); - LIns* args[] = {vp_ins, index_ins, obj_ins, cx_ins}; - ok_ins = lir->insCall(&SetPropertyByIndex_ci, args); - } - guard(true, ok_ins, STATUS_EXIT); - - leaveDeepBailCall(); - return JSRS_CONTINUE; -} +JS_DEFINE_TRCINFO_1(SetProperty, + (4, (extern, BOOL_FAIL, SetProperty_tn, CONTEXT, THIS, STRING, JSVAL, 0, 0))) +JS_DEFINE_TRCINFO_1(SetElement, + (4, (extern, BOOL_FAIL, SetElement_tn, CONTEXT, THIS, INT32, JSVAL, 0, 0))) JS_REQUIRES_STACK JSRecordingStatus TraceRecorder::record_JSOP_SETELEM() @@ -10251,43 +10188,60 @@ TraceRecorder::record_JSOP_SETELEM() LIns* obj_ins = get(&lval); LIns* idx_ins = get(&idx); LIns* v_ins = get(&v); + jsid id; if (!JSVAL_IS_INT(idx)) { if (!JSVAL_IS_PRIMITIVE(idx)) ABORT_TRACE("non-primitive index"); - CHECK_STATUS(initOrSetPropertyByName(obj_ins, &idx, &v, - *cx->fp->regs->pc == JSOP_INITELEM)); - } else if (JSVAL_TO_INT(idx) < 0 || !OBJ_IS_DENSE_ARRAY(cx, obj)) { - CHECK_STATUS(initOrSetPropertyByIndex(obj_ins, idx_ins, &v, - *cx->fp->regs->pc == JSOP_INITELEM)); - } else { - // Fast path: assigning to element of dense array. - // Make sure the array is actually dense. - if (!guardDenseArray(obj, obj_ins, BRANCH_EXIT)) - return JSRS_STOP; + // If index is not a string, turn it into a string. + if (!js_InternNonIntElementId(cx, obj, idx, &id)) + ABORT_TRACE_ERROR("failed to intern non-int element id"); + set(&idx, stringify(idx)); - // The index was on the stack and is therefore a LIR float. Force it to - // be an integer. - idx_ins = makeNumberInt32(idx_ins); + // Store the interned string to the stack to save the interpreter from redoing this work. + idx = ID_TO_VALUE(id); - // Box the value so we can use one builtin instead of having to add one - // builtin for every storage type. Special case for integers though, - // since they are so common. - LIns* res_ins; - if (isNumber(v) && isPromoteInt(v_ins)) { - LIns* args[] = { ::demote(lir, v_ins), idx_ins, obj_ins, cx_ins }; - res_ins = lir->insCall(&js_Array_dense_setelem_int_ci, args); - } else { - LIns* boxed_v_ins = v_ins; - box_jsval(v, boxed_v_ins); + // The object is not guaranteed to be a dense array at this point, so it might be the + // global object, which we have to guard against. + CHECK_STATUS(guardNotGlobalObject(obj, obj_ins)); - LIns* args[] = { boxed_v_ins, idx_ins, obj_ins, cx_ins }; - res_ins = lir->insCall(&js_Array_dense_setelem_ci, args); - } - guard(false, lir->ins_eq0(res_ins), MISMATCH_EXIT); + return call_imacro((*cx->fp->regs->pc == JSOP_INITELEM) + ? initelem_imacros.initprop + : setelem_imacros.setprop); } + if (JSVAL_TO_INT(idx) < 0 || !OBJ_IS_DENSE_ARRAY(cx, obj)) { + CHECK_STATUS(guardNotGlobalObject(obj, obj_ins)); + + return call_imacro((*cx->fp->regs->pc == JSOP_INITELEM) + ? initelem_imacros.initelem + : setelem_imacros.setelem); + } + + // Make sure the array is actually dense. + if (!guardDenseArray(obj, obj_ins, BRANCH_EXIT)) + return JSRS_STOP; + + // Fast path for dense arrays accessed with a non-negative integer index. In case the trace + // calculated the index using the FPU, force it to be an integer. + idx_ins = makeNumberInt32(idx_ins); + + // Box the value so we can use one builtin instead of having to add one builtin for every + // storage type. Special case for integers though, since they are so common. + LIns* res_ins; + if (isNumber(v) && isPromoteInt(v_ins)) { + LIns* args[] = { ::demote(lir, v_ins), idx_ins, obj_ins, cx_ins }; + res_ins = lir->insCall(&js_Array_dense_setelem_int_ci, args); + } else { + LIns* boxed_v_ins = v_ins; + box_jsval(v, boxed_v_ins); + + LIns* args[] = { boxed_v_ins, idx_ins, obj_ins, cx_ins }; + res_ins = lir->insCall(&js_Array_dense_setelem_ci, args); + } + guard(false, lir->ins_eq0(res_ins), MISMATCH_EXIT); + jsbytecode* pc = cx->fp->regs->pc; if (*pc == JSOP_SETELEM && pc[JSOP_SETELEM_LENGTH] != JSOP_POP) set(&lval, v_ins); @@ -11615,38 +11569,41 @@ TraceRecorder::record_JSOP_IN() return JSRS_CONTINUE; } +static JSBool +HasInstance(JSContext *cx, uintN argc, jsval *vp) +{ + jsval *argv; + JS_ASSERT(argc == 1); + argv = JS_ARGV(cx, vp); + JSBool result = JS_FALSE; + JSObject* obj = JS_THIS_OBJECT(cx, vp); + if (!obj->map->ops->hasInstance(cx, obj, argv[0], &result)) + return JS_FALSE; + JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(result)); + return JS_TRUE; +} + static JSBool FASTCALL -HasInstance(JSContext* cx, JSObject* ctor, jsval val) +HasInstance_tn(JSContext* cx, JSObject* obj, jsval v) { JSBool result = JS_FALSE; - if (!ctor->map->ops->hasInstance(cx, ctor, val, &result)) + if (!obj->map->ops->hasInstance(cx, obj, v, &result)) js_SetBuiltinError(cx); return result; } -JS_DEFINE_CALLINFO_3(static, BOOL_FAIL, HasInstance, CONTEXT, OBJECT, JSVAL, 0, 0) + +JS_DEFINE_TRCINFO_1(HasInstance, + (3, (extern, BOOL_FAIL, HasInstance_tn, CONTEXT, THIS, JSVAL, 0, 0))) JS_REQUIRES_STACK JSRecordingStatus TraceRecorder::record_JSOP_INSTANCEOF() { - // If the rhs isn't an object, we are headed for a TypeError. - jsval& ctor = stackval(-1); - if (JSVAL_IS_PRIMITIVE(ctor)) - ABORT_TRACE("non-object on rhs of instanceof"); + jsval& r = stackval(-1); - jsval& val = stackval(-2); - LIns* val_ins = get(&val); - box_jsval(val, val_ins); + if (!JSVAL_IS_PRIMITIVE(r)) + return call_imacro(instanceof_imacros.instanceof); - enterDeepBailCall(); - LIns* args[] = {val_ins, get(&ctor), cx_ins}; - stack(-2, lir->insCall(&HasInstance_ci, args)); - LIns* status_ins = lir->insLoad(LIR_ld, - lirbuf->state, - (int) offsetof(InterpState, builtinStatus)); - guard(true, lir->ins_eq0(status_ins), STATUS_EXIT); - leaveDeepBailCall(); - - return JSRS_CONTINUE; + return JSRS_STOP; } JS_REQUIRES_STACK JSRecordingStatus @@ -12630,6 +12587,9 @@ static const struct BuiltinFunctionInfo { } builtinFunctionInfo[JSBUILTIN_LIMIT] = { {ObjectToIterator_trcinfo, 1}, {CallIteratorNext_trcinfo, 0}, + {SetProperty_trcinfo, 2}, + {SetElement_trcinfo, 2}, + {HasInstance_trcinfo, 1} }; JSObject * diff --git a/js/src/jstracer.h b/js/src/jstracer.h index 75baacbfe349..d56bf1ad070a 100644 --- a/js/src/jstracer.h +++ b/js/src/jstracer.h @@ -808,7 +808,6 @@ class TraceRecorder : public avmplus::GCObject { JS_REQUIRES_STACK void enterDeepBailCall(); JS_REQUIRES_STACK void leaveDeepBailCall(); - JS_REQUIRES_STACK JSRecordingStatus primitiveToStringInPlace(jsval* vp); JS_REQUIRES_STACK void finishGetProp(nanojit::LIns* obj_ins, nanojit::LIns* vp_ins, nanojit::LIns* ok_ins, jsval* outp); JS_REQUIRES_STACK JSRecordingStatus getPropertyByName(nanojit::LIns* obj_ins, jsval* idvalp, @@ -825,12 +824,6 @@ class TraceRecorder : public avmplus::GCObject { JS_REQUIRES_STACK JSRecordingStatus setCallProp(JSObject *callobj, nanojit::LIns *callobj_ins, JSScopeProperty *sprop, nanojit::LIns *v_ins, jsval v); - JS_REQUIRES_STACK JSRecordingStatus initOrSetPropertyByName(nanojit::LIns* obj_ins, - jsval* idvalp, jsval* rvalp, - bool init); - JS_REQUIRES_STACK JSRecordingStatus initOrSetPropertyByIndex(nanojit::LIns* obj_ins, - nanojit::LIns* index_ins, - jsval* rvalp, bool init); JS_REQUIRES_STACK void box_jsval(jsval v, nanojit::LIns*& v_ins); JS_REQUIRES_STACK void unbox_jsval(jsval v, nanojit::LIns*& v_ins, VMSideExit* exit); diff --git a/js/src/trace-test.js b/js/src/trace-test.js index 49d8cd394ab4..7e5eb747fa84 100644 --- a/js/src/trace-test.js +++ b/js/src/trace-test.js @@ -5706,36 +5706,6 @@ function doParseIntTests() { } doParseIntTests(); -function testSetelemWithFloatIndex() { - var x, a = {}; - for (var i = 0; i < 9; i++) - x = a[-3.5] = "ok"; - assertEq(x, "ok"); -} -test(testSetelemWithFloatIndex); - -function testInitelemWithSetter() { // bug 509843 - Object.prototype.__defineSetter__(1, function () { throw "fabulous fit"; }); - for (var i =0; i<9; i++) - ({1:'a'}); -} -test(testInitelemWithSetter); - -function testDeepBailFromHasInstance() { - var arr = [StopIteration, StopIteration, StopIteration, StopIteration, {}]; - var obj = {}; - var x; - var result = 'no error'; - try { - for (var i = 0; i < arr.length; i++) - x = (obj instanceof arr[i]); // last iteration throws, triggering deep bail - } catch (exc) { - result = exc.constructor.name; - } - assertEq(result, 'TypeError'); -} -test(testDeepBailFromHasInstance); - /***************************************************************************** * * * _____ _ _ _____ ______ _____ _______ *