mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Record JSOP_IN (452563, r=gal).
This commit is contained in:
parent
044f0f4026
commit
bea371d215
@ -76,6 +76,7 @@ BUILTIN2(CloseIterator, LO, LO, LO, bool, JSContext*, jsval, 0,
|
|||||||
BUILTIN2(CallTree, LO, LO, P, nanojit::GuardRecord*, avmplus::InterpState*, nanojit::Fragment*, 0, 0)
|
BUILTIN2(CallTree, LO, LO, P, nanojit::GuardRecord*, avmplus::InterpState*, nanojit::Fragment*, 0, 0)
|
||||||
BUILTIN2(FastNewObject, LO, LO, P, JSObject*, JSContext*, JSObject*, 0, 0)
|
BUILTIN2(FastNewObject, LO, LO, P, JSObject*, JSContext*, JSObject*, 0, 0)
|
||||||
BUILTIN3(AddProperty, LO, LO, LO, LO, bool, JSContext*, JSObject*, JSScopeProperty*, 0, 0)
|
BUILTIN3(AddProperty, LO, LO, LO, LO, bool, JSContext*, JSObject*, JSScopeProperty*, 0, 0)
|
||||||
|
BUILTIN3(HasNamedProperty, LO, LO, LO, LO, bool, JSContext*, JSObject*, JSString*, 0, 0)
|
||||||
BUILTIN3(CallGetter, LO, LO, LO, P, jsval, JSContext*, JSObject*, JSScopeProperty*, 0, 0)
|
BUILTIN3(CallGetter, LO, LO, LO, P, jsval, JSContext*, JSObject*, JSScopeProperty*, 0, 0)
|
||||||
BUILTIN2(TypeOfObject, LO, LO, P, JSString*, JSContext*, JSObject*, 1, 1)
|
BUILTIN2(TypeOfObject, LO, LO, P, JSString*, JSContext*, JSObject*, 1, 1)
|
||||||
BUILTIN2(TypeOfBoolean, LO, LO, P, JSString*, JSContext*, jsint, 1, 1)
|
BUILTIN2(TypeOfBoolean, LO, LO, P, JSString*, JSContext*, jsint, 1, 1)
|
||||||
|
@ -530,6 +530,22 @@ js_AddProperty(JSContext* cx, JSObject* obj, JSScopeProperty* sprop)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FASTCALL
|
||||||
|
js_HasNamedProperty(JSContext* cx, JSObject* obj, JSString* idstr)
|
||||||
|
{
|
||||||
|
jsid id;
|
||||||
|
if (!js_ValueToStringId(cx, STRING_TO_JSVAL(idstr), &id))
|
||||||
|
return JSVAL_ERROR_COOKIE;
|
||||||
|
|
||||||
|
JSObject* obj2;
|
||||||
|
JSProperty* prop;
|
||||||
|
if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop))
|
||||||
|
return JSVAL_TO_BOOLEAN(JSVAL_VOID);
|
||||||
|
if (prop)
|
||||||
|
OBJ_DROP_PROPERTY(cx, obj2, prop);
|
||||||
|
return prop != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
jsval FASTCALL
|
jsval FASTCALL
|
||||||
js_CallGetter(JSContext* cx, JSObject* obj, JSScopeProperty* sprop)
|
js_CallGetter(JSContext* cx, JSObject* obj, JSScopeProperty* sprop)
|
||||||
{
|
{
|
||||||
|
@ -3127,6 +3127,23 @@ js_Interpret(JSContext *cx)
|
|||||||
} \
|
} \
|
||||||
JS_END_MACRO
|
JS_END_MACRO
|
||||||
|
|
||||||
|
#define TRY_BRANCH_AFTER_COND(cond,spdec) \
|
||||||
|
JS_BEGIN_MACRO \
|
||||||
|
uintN diff_; \
|
||||||
|
JS_ASSERT(js_CodeSpec[op].length == 1); \
|
||||||
|
diff_ = (uintN) regs.pc[1] - (uintN) JSOP_IFEQ; \
|
||||||
|
if (diff_ <= 1) { \
|
||||||
|
regs.sp -= spdec; \
|
||||||
|
if (cond == (diff_ != 0)) { \
|
||||||
|
++regs.pc; \
|
||||||
|
len = GET_JUMP_OFFSET(regs.pc); \
|
||||||
|
BRANCH(len); \
|
||||||
|
} \
|
||||||
|
len = 1 + JSOP_IFEQ_LENGTH; \
|
||||||
|
DO_NEXT_OP(len); \
|
||||||
|
} \
|
||||||
|
JS_END_MACRO
|
||||||
|
|
||||||
BEGIN_CASE(JSOP_IN)
|
BEGIN_CASE(JSOP_IN)
|
||||||
rval = FETCH_OPND(-1);
|
rval = FETCH_OPND(-1);
|
||||||
if (JSVAL_IS_PRIMITIVE(rval)) {
|
if (JSVAL_IS_PRIMITIVE(rval)) {
|
||||||
@ -3137,10 +3154,12 @@ js_Interpret(JSContext *cx)
|
|||||||
FETCH_ELEMENT_ID(obj, -2, id);
|
FETCH_ELEMENT_ID(obj, -2, id);
|
||||||
if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop))
|
if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop))
|
||||||
goto error;
|
goto error;
|
||||||
regs.sp--;
|
cond = prop != NULL;
|
||||||
STORE_OPND(-1, BOOLEAN_TO_JSVAL(prop != NULL));
|
|
||||||
if (prop)
|
if (prop)
|
||||||
OBJ_DROP_PROPERTY(cx, obj2, prop);
|
OBJ_DROP_PROPERTY(cx, obj2, prop);
|
||||||
|
TRY_BRANCH_AFTER_COND(cond, 2);
|
||||||
|
regs.sp--;
|
||||||
|
STORE_OPND(-1, BOOLEAN_TO_JSVAL(cond));
|
||||||
END_CASE(JSOP_IN)
|
END_CASE(JSOP_IN)
|
||||||
|
|
||||||
BEGIN_CASE(JSOP_ITER)
|
BEGIN_CASE(JSOP_ITER)
|
||||||
@ -3484,23 +3503,6 @@ js_Interpret(JSContext *cx)
|
|||||||
BITWISE_OP(&);
|
BITWISE_OP(&);
|
||||||
END_CASE(JSOP_BITAND)
|
END_CASE(JSOP_BITAND)
|
||||||
|
|
||||||
#define TRY_BRANCH_AFTER_COND(cond,spdec) \
|
|
||||||
JS_BEGIN_MACRO \
|
|
||||||
uintN diff_; \
|
|
||||||
JS_ASSERT(js_CodeSpec[op].length == 1); \
|
|
||||||
diff_ = (uintN) regs.pc[1] - (uintN) JSOP_IFEQ; \
|
|
||||||
if (diff_ <= 1) { \
|
|
||||||
regs.sp -= spdec; \
|
|
||||||
if (cond == (diff_ != 0)) { \
|
|
||||||
++regs.pc; \
|
|
||||||
len = GET_JUMP_OFFSET(regs.pc); \
|
|
||||||
BRANCH(len); \
|
|
||||||
} \
|
|
||||||
len = 1 + JSOP_IFEQ_LENGTH; \
|
|
||||||
DO_NEXT_OP(len); \
|
|
||||||
} \
|
|
||||||
JS_END_MACRO
|
|
||||||
|
|
||||||
#define RELATIONAL_OP(OP) \
|
#define RELATIONAL_OP(OP) \
|
||||||
JS_BEGIN_MACRO \
|
JS_BEGIN_MACRO \
|
||||||
rval = FETCH_OPND(-1); \
|
rval = FETCH_OPND(-1); \
|
||||||
|
@ -2420,7 +2420,9 @@ TraceRecorder::ifop()
|
|||||||
jsdouble d = asNumber(v);
|
jsdouble d = asNumber(v);
|
||||||
jsdpun u;
|
jsdpun u;
|
||||||
u.d = 0;
|
u.d = 0;
|
||||||
guard((d == 0 || JSDOUBLE_IS_NaN(d)), lir->ins2(LIR_feq, get(&v), lir->insImmq(u.u64)), BRANCH_EXIT);
|
guard(d == 0 || JSDOUBLE_IS_NaN(d),
|
||||||
|
lir->ins2(LIR_feq, get(&v), lir->insImmq(u.u64)),
|
||||||
|
BRANCH_EXIT);
|
||||||
} else if (JSVAL_IS_STRING(v)) {
|
} else if (JSVAL_IS_STRING(v)) {
|
||||||
guard(JSSTRING_LENGTH(JSVAL_TO_STRING(v)) == 0,
|
guard(JSSTRING_LENGTH(JSVAL_TO_STRING(v)) == 0,
|
||||||
lir->ins_eq0(lir->ins2(LIR_piand,
|
lir->ins_eq0(lir->ins2(LIR_piand,
|
||||||
@ -3782,7 +3784,7 @@ TraceRecorder::record_JSOP_SETPROP()
|
|||||||
JSObject* obj = JSVAL_TO_OBJECT(l);
|
JSObject* obj = JSVAL_TO_OBJECT(l);
|
||||||
|
|
||||||
if (obj->map->ops->setProperty != js_SetProperty)
|
if (obj->map->ops->setProperty != js_SetProperty)
|
||||||
ABORT_TRACE("non-native setProperty");
|
ABORT_TRACE("non-native JSObjectOps::setProperty");
|
||||||
|
|
||||||
LIns* obj_ins = get(&l);
|
LIns* obj_ins = get(&l);
|
||||||
|
|
||||||
@ -4881,7 +4883,82 @@ TraceRecorder::record_JSOP_THROW()
|
|||||||
bool
|
bool
|
||||||
TraceRecorder::record_JSOP_IN()
|
TraceRecorder::record_JSOP_IN()
|
||||||
{
|
{
|
||||||
return false;
|
jsval& rval = stackval(-1);
|
||||||
|
if (JSVAL_IS_PRIMITIVE(rval))
|
||||||
|
ABORT_TRACE("JSOP_IN on non-object right operand");
|
||||||
|
|
||||||
|
jsval& lval = stackval(-2);
|
||||||
|
if (!JSVAL_IS_PRIMITIVE(lval))
|
||||||
|
ABORT_TRACE("JSOP_IN on E4X QName left operand");
|
||||||
|
|
||||||
|
jsid id;
|
||||||
|
if (JSVAL_IS_INT(lval)) {
|
||||||
|
id = INT_JSVAL_TO_JSID(lval);
|
||||||
|
} else {
|
||||||
|
if (!js_ValueToStringId(cx, lval, &id))
|
||||||
|
ABORT_TRACE("OOM under js_ValueToStringId in JSOP_IN");
|
||||||
|
lval = ID_TO_VALUE(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expect what we see at trace recording time (hit or miss) to be the same
|
||||||
|
// when executing the trace. Use a builtin helper for named properties, as
|
||||||
|
// forInLoop does. First, handle indexes in dense arrays as a special case.
|
||||||
|
JSObject* obj = JSVAL_TO_OBJECT(rval);
|
||||||
|
LIns* obj_ins = get(&rval);
|
||||||
|
|
||||||
|
bool cond;
|
||||||
|
LIns* x;
|
||||||
|
do {
|
||||||
|
if (guardDenseArray(obj, obj_ins)) {
|
||||||
|
if (JSVAL_IS_INT(lval)) {
|
||||||
|
jsint idx = JSVAL_TO_INT(lval);
|
||||||
|
LIns* idx_ins = f2i(get(&lval));
|
||||||
|
LIns* dslots_ins = lir->insLoad(LIR_ldp, obj_ins, offsetof(JSObject, dslots));
|
||||||
|
if (!guardDenseArrayIndex(obj, idx, obj_ins, dslots_ins, idx_ins))
|
||||||
|
ABORT_TRACE("dense array index out of bounds");
|
||||||
|
|
||||||
|
cond = obj->dslots[idx] != JSVAL_HOLE;
|
||||||
|
x = lir->ins_eq0(lir->ins2(LIR_eq,
|
||||||
|
lir->insLoad(LIR_ldp, dslots_ins, idx * sizeof(jsval)),
|
||||||
|
INS_CONST(JSVAL_HOLE)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not an index id, but a dense array -- go up to the proto. */
|
||||||
|
obj = STOBJ_GET_PROTO(obj);
|
||||||
|
obj_ins = stobj_get_fslot(obj_ins, JSSLOT_PROTO);
|
||||||
|
} else {
|
||||||
|
if (JSVAL_IS_INT(id))
|
||||||
|
ABORT_TRACE("INT in OBJ where OBJ is not a dense array");
|
||||||
|
}
|
||||||
|
|
||||||
|
JSObject* obj2;
|
||||||
|
JSProperty* prop;
|
||||||
|
if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop))
|
||||||
|
ABORT_TRACE("OBJ_LOOKUP_PROPERTY failed in JSOP_IN");
|
||||||
|
|
||||||
|
cond = prop != NULL;
|
||||||
|
if (prop)
|
||||||
|
OBJ_DROP_PROPERTY(cx, obj2, prop);
|
||||||
|
|
||||||
|
LIns* args[] = { get(&lval), obj_ins, cx_ins };
|
||||||
|
x = lir->insCall(F_HasNamedProperty, args);
|
||||||
|
guard(false, lir->ins2i(LIR_eq, x, 2), OOM_EXIT);
|
||||||
|
x = lir->ins2i(LIR_eq, x, 1);
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
/* The interpreter fuses comparisons and the following branch,
|
||||||
|
so we have to do that here as well. */
|
||||||
|
if (cx->fp->regs->pc[1] == JSOP_IFEQ || cx->fp->regs->pc[1] == JSOP_IFNE)
|
||||||
|
guard(cond, x, BRANCH_EXIT);
|
||||||
|
|
||||||
|
/* We update the stack after the guard. This is safe since
|
||||||
|
the guard bails out at the comparison and the interpreter
|
||||||
|
will this re-execute the comparison. This way the
|
||||||
|
value of the condition doesn't have to be calculated and
|
||||||
|
saved on the stack in most cases. */
|
||||||
|
set(&lval, x);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -849,6 +849,32 @@ function forVarInWith() {
|
|||||||
forVarInWith.expected = "pqrst";
|
forVarInWith.expected = "pqrst";
|
||||||
test(forVarInWith);
|
test(forVarInWith);
|
||||||
|
|
||||||
|
function inObjectTest() {
|
||||||
|
var o = {p: 1, q: 2, r: 3, s: 4, t: 5};
|
||||||
|
var r = 0;
|
||||||
|
for (var i in o) {
|
||||||
|
if (!(i in o))
|
||||||
|
break;
|
||||||
|
if ((i + i) in o)
|
||||||
|
break;
|
||||||
|
++r;
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
inObjectTest.expected = 5;
|
||||||
|
test(inObjectTest);
|
||||||
|
|
||||||
|
function inArrayTest() {
|
||||||
|
var a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||||
|
for (var i = 0; i < a.length; i++) {
|
||||||
|
if (!(i in a))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
inArrayTest.expected = 10;
|
||||||
|
test(inArrayTest);
|
||||||
|
|
||||||
/* Keep these at the end so that we can see the summary after the trace-debug spew. */
|
/* Keep these at the end so that we can see the summary after the trace-debug spew. */
|
||||||
print("\npassed:", passes.length && passes.join(","));
|
print("\npassed:", passes.length && passes.join(","));
|
||||||
print("\nFAILED:", fails.length && fails.join(","));
|
print("\nFAILED:", fails.length && fails.join(","));
|
||||||
|
Loading…
Reference in New Issue
Block a user