mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-31 22:25:30 +00:00
Backed out bug 508051. Fails trace-test/mandelbrot.
This commit is contained in:
parent
6491ab9bf9
commit
99424f7beb
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 *
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* _____ _ _ _____ ______ _____ _______ *
|
||||
|
Loading…
Reference in New Issue
Block a user