Move GETELEM/SETELEM operations to jsinterpinlines (bug 718683, r=pierron)

This commit is contained in:
Jan de Mooij 2012-01-24 16:20:34 +01:00
parent c34267eb99
commit 796259b65c
5 changed files with 146 additions and 112 deletions

View File

@ -1108,6 +1108,7 @@ class TypeScript
*/
static inline void Monitor(JSContext *cx, JSScript *script, jsbytecode *pc,
const js::Value &val);
static inline void Monitor(JSContext *cx, const js::Value &rval);
/* Monitor an assignment at a SETELEM on a non-integer identifier. */
static inline void MonitorAssign(JSContext *cx, JSScript *script, jsbytecode *pc,

View File

@ -629,6 +629,15 @@ TypeScript::MonitorUnknown(JSContext *cx)
MonitorUnknown(cx, script, pc);
}
/* static */ inline void
TypeScript::Monitor(JSContext *cx, const js::Value &rval)
{
JSScript *script;
jsbytecode *pc;
GetPcScript(cx, &script, &pc);
Monitor(cx, script, pc, rval);
}
/* static */ inline void
TypeScript::MonitorAssign(JSContext *cx, JSScript *script, jsbytecode *pc,
JSObject *obj, jsid id, const js::Value &rval)

View File

@ -2721,78 +2721,8 @@ BEGIN_CASE(JSOP_GETELEM)
{
Value &lref = regs.sp[-2];
Value &rref = regs.sp[-1];
Value &rval = regs.sp[-2];
if (lref.isString() && rref.isInt32()) {
JSString *str = lref.toString();
int32_t i = rref.toInt32();
if (size_t(i) < str->length()) {
str = cx->runtime->staticStrings.getUnitStringForElement(cx, str, size_t(i));
if (!str)
goto error;
rval.setString(str);
TypeScript::Monitor(cx, script, regs.pc, rval);
regs.sp--;
len = JSOP_GETELEM_LENGTH;
DO_NEXT_OP(len);
}
}
if (lref.isMagic(JS_LAZY_ARGUMENTS)) {
if (rref.isInt32() && size_t(rref.toInt32()) < regs.fp()->numActualArgs()) {
rval = regs.fp()->canonicalActualArg(rref.toInt32());
TypeScript::Monitor(cx, script, regs.pc, rval);
regs.sp--;
len = JSOP_GETELEM_LENGTH;
DO_NEXT_OP(len);
}
MarkArgumentsCreated(cx, script);
JS_ASSERT(!lref.isMagic(JS_LAZY_ARGUMENTS));
}
JSObject *obj;
VALUE_TO_OBJECT(cx, &lref, obj);
uint32_t index;
if (IsDefinitelyIndex(rref, &index)) {
if (obj->isDenseArray()) {
if (index < obj->getDenseArrayInitializedLength()) {
rval = obj->getDenseArrayElement(index);
if (!rval.isMagic())
goto end_getelem;
}
} else if (obj->isArguments()) {
if (obj->asArguments().getElement(index, &rval))
goto end_getelem;
}
if (!obj->getElement(cx, index, &rval))
goto error;
} else {
if (script->hasAnalysis())
script->analysis()->getCode(regs.pc).getStringElement = true;
SpecialId special;
if (ValueIsSpecial(obj, &rref, &special, cx)) {
if (!obj->getSpecial(cx, obj, special, &rval))
goto error;
} else {
JSAtom *name;
if (!js_ValueToAtom(cx, rref, &name))
goto error;
if (name->isIndex(&index)) {
if (!obj->getElement(cx, index, &rval))
goto error;
} else {
if (!obj->getProperty(cx, name->asPropertyName(), &rval))
goto error;
}
}
}
end_getelem:
assertSameCompartment(cx, rval);
TypeScript::Monitor(cx, script, regs.pc, rval);
if (!GetElementOperation(cx, lref, rref, &regs.sp[-2]))
goto error;
regs.sp--;
}
END_CASE(JSOP_GETELEM)
@ -2832,32 +2762,10 @@ BEGIN_CASE(JSOP_SETELEM)
FETCH_OBJECT(cx, -3, obj);
jsid id;
FETCH_ELEMENT_ID(obj, -2, id);
Value rval;
TypeScript::MonitorAssign(cx, script, regs.pc, obj, id, regs.sp[-1]);
do {
if (obj->isDenseArray() && JSID_IS_INT(id)) {
jsuint length = obj->getDenseArrayInitializedLength();
jsint i = JSID_TO_INT(id);
if ((jsuint)i < length) {
if (obj->getDenseArrayElement(i).isMagic(JS_ARRAY_HOLE)) {
if (js_PrototypeHasIndexedProperties(cx, obj))
break;
if ((jsuint)i >= obj->getArrayLength())
obj->setArrayLength(cx, i + 1);
}
obj->setDenseArrayElementWithType(cx, i, regs.sp[-1]);
goto end_setelem;
} else {
if (script->hasAnalysis())
script->analysis()->getCode(regs.pc).arrayWriteHole = true;
}
}
} while (0);
rval = regs.sp[-1];
if (!obj->setGeneric(cx, id, &rval, script->strictModeCode))
Value &value = regs.sp[-1];
if (!SetObjectElementOperation(cx, obj, id, value))
goto error;
end_setelem:
regs.sp[-3] = regs.sp[-1];
regs.sp[-3] = value;
regs.sp -= 2;
}
END_CASE(JSOP_SETELEM)

View File

@ -645,6 +645,133 @@ ModOperation(JSContext *cx, const Value &lhs, const Value &rhs, Value *res)
return true;
}
static inline bool
FetchElementId(JSContext *cx, JSObject *obj, const Value &idval, jsid &id, Value *vp)
{
int32_t i_;
if (ValueFitsInInt32(idval, &i_) && INT_FITS_IN_JSID(i_)) {
id = INT_TO_JSID(i_);
return true;
}
return !!js_InternNonIntElementId(cx, obj, idval, &id, vp);
}
static JS_ALWAYS_INLINE bool
GetObjectElementOperation(JSContext *cx, JSObject *obj, const Value &rref, Value *res)
{
JSScript *script;
jsbytecode *pc;
types::TypeScript::GetPcScript(cx, &script, &pc);
uint32_t index;
if (IsDefinitelyIndex(rref, &index)) {
do {
if (obj->isDenseArray()) {
if (index < obj->getDenseArrayInitializedLength()) {
*res = obj->getDenseArrayElement(index);
if (!res->isMagic())
break;
}
} else if (obj->isArguments()) {
if (obj->asArguments().getElement(index, res))
break;
}
if (!obj->getElement(cx, index, res))
return false;
} while(0);
} else {
if (script->hasAnalysis())
script->analysis()->getCode(pc).getStringElement = true;
SpecialId special;
*res = rref;
if (ValueIsSpecial(obj, res, &special, cx)) {
if (!obj->getSpecial(cx, obj, special, res))
return false;
} else {
JSAtom *name;
if (!js_ValueToAtom(cx, *res, &name))
return false;
if (name->isIndex(&index)) {
if (!obj->getElement(cx, index, res))
return false;
} else {
if (!obj->getProperty(cx, name->asPropertyName(), res))
return false;
}
}
}
assertSameCompartment(cx, *res);
types::TypeScript::Monitor(cx, script, pc, *res);
return true;
}
static JS_ALWAYS_INLINE bool
GetElementOperation(JSContext *cx, const Value &lref, const Value &rref, Value *res)
{
if (lref.isString() && rref.isInt32()) {
JSString *str = lref.toString();
int32_t i = rref.toInt32();
if (size_t(i) < str->length()) {
str = cx->runtime->staticStrings.getUnitStringForElement(cx, str, size_t(i));
if (!str)
return false;
res->setString(str);
types::TypeScript::Monitor(cx, *res);
return true;
}
}
if (lref.isMagic(JS_LAZY_ARGUMENTS)) {
if (rref.isInt32() && size_t(rref.toInt32()) < cx->regs().fp()->numActualArgs()) {
*res = cx->regs().fp()->canonicalActualArg(rref.toInt32());
types::TypeScript::Monitor(cx, *res);
return true;
}
types::MarkArgumentsCreated(cx, cx->fp()->script());
JS_ASSERT(!lref.isMagic(JS_LAZY_ARGUMENTS));
}
JSObject *obj = ValueToObject(cx, lref);
if (!obj)
return false;
return GetObjectElementOperation(cx, obj, rref, res);
}
static JS_ALWAYS_INLINE bool
SetObjectElementOperation(JSContext *cx, JSObject *obj, jsid id, const Value &value)
{
JSScript *script;
jsbytecode *pc;
types::TypeScript::GetPcScript(cx, &script, &pc);
types::TypeScript::MonitorAssign(cx, script, pc, obj, id, value);
do {
if (obj->isDenseArray() && JSID_IS_INT(id)) {
jsuint length = obj->getDenseArrayInitializedLength();
jsint i = JSID_TO_INT(id);
if ((jsuint)i < length) {
if (obj->getDenseArrayElement(i).isMagic(JS_ARRAY_HOLE)) {
if (js_PrototypeHasIndexedProperties(cx, obj))
break;
if ((jsuint)i >= obj->getArrayLength())
obj->setArrayLength(cx, i + 1);
}
obj->setDenseArrayElementWithType(cx, i, value);
return true;
} else {
if (script->hasAnalysis())
script->analysis()->getCode(pc).arrayWriteHole = true;
}
}
} while (0);
Value tmp = value;
return obj->setGeneric(cx, id, &tmp, script->strictModeCode);
}
} /* namespace js */
#endif /* jsinterpinlines_h__ */

View File

@ -210,17 +210,6 @@ stubs::GetElem(VMFrame &f)
#endif
}
static inline bool
FetchElementId(VMFrame &f, JSObject *obj, const Value &idval, jsid &id, Value *vp)
{
int32_t i_;
if (ValueFitsInInt32(idval, &i_) && INT_FITS_IN_JSID(i_)) {
id = INT_TO_JSID(i_);
return true;
}
return !!js_InternNonIntElementId(f.cx, obj, idval, &id, vp);
}
template<JSBool strict>
void JS_FASTCALL
stubs::SetElem(VMFrame &f)
@ -239,7 +228,7 @@ stubs::SetElem(VMFrame &f)
if (!obj)
THROW();
if (!FetchElementId(f, obj, idval, id, &regs.sp[-2]))
if (!FetchElementId(f.cx, obj, idval, id, &regs.sp[-2]))
THROW();
TypeScript::MonitorAssign(cx, f.script(), f.pc(), obj, id, rval);
@ -287,7 +276,7 @@ stubs::ToId(VMFrame &f)
THROW();
jsid id;
if (!FetchElementId(f, obj, idval, id, &idval))
if (!FetchElementId(f.cx, obj, idval, id, &idval))
THROW();
if (!idval.isInt32())
@ -1032,7 +1021,7 @@ stubs::InitElem(VMFrame &f, uint32_t last)
/* Fetch id now that we have obj. */
jsid id;
const Value &idval = regs.sp[-2];
if (!FetchElementId(f, obj, idval, id, &regs.sp[-2]))
if (!FetchElementId(f.cx, obj, idval, id, &regs.sp[-2]))
THROW();
/*
@ -1744,7 +1733,7 @@ stubs::In(VMFrame &f)
JSObject *obj = &rref.toObject();
jsid id;
if (!FetchElementId(f, obj, f.regs.sp[-2], id, &f.regs.sp[-2]))
if (!FetchElementId(f.cx, obj, f.regs.sp[-2], id, &f.regs.sp[-2]))
THROWV(JS_FALSE);
JSObject *obj2;