Bug 664824 - JM+TI: Make JSOP_IN fast for dense arrays. r=jandem

This commit is contained in:
Marco Castelluccio 2012-01-25 14:55:00 +01:00
parent a71396ead0
commit 3352dc9370
4 changed files with 107 additions and 5 deletions

View File

@ -0,0 +1,21 @@
function f(arr, b) {
var res = "";
var a;
if (b)
a = arr;
for (var i=100; i>-200; i--) {
if (i in a) {
res += i;
}
}
return res;
}
assertEq(f([1, , 2, 3], true), "320");
try {
f([1, , 2, 3], false);
assertEq(0, 1);
} catch(e) {
assertEq(e instanceof TypeError, true);
}

View File

@ -791,6 +791,20 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::MIPSRegiste
return branch32(cond, extent, key.reg());
}
Jump guardElementNotHole(RegisterID elements, const Int32Key &key) {
Jump jmp;
if (key.isConstant()) {
Address slot(elements, key.index() * sizeof(Value));
jmp = guardNotHole(slot);
} else {
BaseIndex slot(elements, key.reg(), JSVAL_SCALE);
jmp = guardNotHole(slot);
}
return jmp;
}
// Load a jsval from an array slot, given a key. |objReg| is clobbered.
FastArrayLoadFails fastArrayLoad(RegisterID objReg, const Int32Key &key,
RegisterID typeReg, RegisterID dataReg) {

View File

@ -2966,11 +2966,7 @@ mjit::Compiler::generateMethod()
BEGIN_CASE(JSOP_IN)
{
prepareStubCall(Uses(2));
INLINE_STUBCALL(stubs::In, REJOIN_PUSH_BOOLEAN);
frame.popn(2);
frame.takeReg(Registers::ReturnReg);
frame.pushTypedPayload(JSVAL_TYPE_BOOLEAN, Registers::ReturnReg);
jsop_in();
}
END_CASE(JSOP_IN)
@ -7448,6 +7444,76 @@ mjit::Compiler::jsop_toid()
stubcc.rejoin(Changes(1));
}
void
mjit::Compiler::jsop_in()
{
FrameEntry *obj = frame.peek(-1);
FrameEntry *id = frame.peek(-2);
if (cx->typeInferenceEnabled() && id->isType(JSVAL_TYPE_INT32)) {
types::TypeSet *types = analysis->poppedTypes(PC, 0);
if (obj->mightBeType(JSVAL_TYPE_OBJECT) &&
!types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_DENSE_ARRAY) &&
!types::ArrayPrototypeHasIndexedProperty(cx, outerScript))
{
bool isPacked = !types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_PACKED_ARRAY);
if (!obj->isTypeKnown()) {
Jump guard = frame.testObject(Assembler::NotEqual, obj);
stubcc.linkExit(guard, Uses(2));
}
RegisterID dataReg = frame.copyDataIntoReg(obj);
Int32Key key = id->isConstant()
? Int32Key::FromConstant(id->getValue().toInt32())
: Int32Key::FromRegister(frame.tempRegForData(id));
masm.loadPtr(Address(dataReg, JSObject::offsetOfElements()), dataReg);
// Guard on the array's initialized length.
Jump initlenGuard = masm.guardArrayExtent(ObjectElements::offsetOfInitializedLength(),
dataReg, key, Assembler::BelowOrEqual);
// Guard to make sure we don't have a hole. Skip it if the array is packed.
MaybeJump holeCheck;
if (!isPacked)
holeCheck = masm.guardElementNotHole(dataReg, key);
masm.move(Imm32(1), dataReg);
Jump done = masm.jump();
Label falseBranch = masm.label();
initlenGuard.linkTo(falseBranch, &masm);
if (!isPacked)
holeCheck.getJump().linkTo(falseBranch, &masm);
masm.move(Imm32(0), dataReg);
done.linkTo(masm.label(), &masm);
stubcc.leave();
OOL_STUBCALL_USES(stubs::In, REJOIN_PUSH_BOOLEAN, Uses(2));
frame.popn(2);
if (dataReg != Registers::ReturnReg)
stubcc.masm.move(Registers::ReturnReg, dataReg);
frame.pushTypedPayload(JSVAL_TYPE_BOOLEAN, dataReg);
stubcc.rejoin(Changes(2));
return;
}
}
prepareStubCall(Uses(2));
INLINE_STUBCALL(stubs::In, REJOIN_PUSH_BOOLEAN);
frame.popn(2);
frame.takeReg(Registers::ReturnReg);
frame.pushTypedPayload(JSVAL_TYPE_BOOLEAN, Registers::ReturnReg);
}
/*
* For any locals or args which we know to be integers but are treated as
* doubles by the type inference, convert to double. These will be assumed to be

View File

@ -753,6 +753,7 @@ private:
CompileStatus jsop_equality_obj_obj(JSOp op, jsbytecode *target, JSOp fused);
bool jsop_equality_int_string(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused);
void jsop_pos();
void jsop_in();
static inline Assembler::Condition
GetCompareCondition(JSOp op, JSOp fused)