Bug 837639 - Convert int32 values to double when convertDoubleElements is set. r=djvj

This commit is contained in:
Jan de Mooij 2013-02-05 11:14:49 +01:00
parent 3769419a6f
commit 42115d95b5
7 changed files with 58 additions and 2 deletions

View File

@ -2082,12 +2082,26 @@ ICSetElem_Dense::Compiler::generateStubCode(MacroAssembler &masm)
BaseIndex element(scratchReg, key, TimesEight);
masm.branchTestMagic(Assembler::Equal, element, &failure);
// Convert int32 values to double if convertDoubleElements is set. In this
// case the heap typeset is guaranteed to contain both int32 and double, so
// it's okay to store a double.
Label convertDoubles, convertDoublesDone;
Address convertDoublesAddr(scratchReg, ObjectElements::offsetOfConvertDoubleElements());
masm.branch32(Assembler::NotEqual, convertDoublesAddr, Imm32(0), &convertDoubles);
masm.bind(&convertDoublesDone);
// It's safe to overwrite R0 now.
masm.loadValue(Address(BaselineStackReg, ICStackValueOffset), R0);
Address valueAddr(BaselineStackReg, ICStackValueOffset);
masm.loadValue(valueAddr, R0);
masm.patchableCallPreBarrier(element, MIRType_Value);
masm.storeValue(R0, element);
EmitReturnFromIC(masm);
// Convert to double and jump back.
masm.bind(&convertDoubles);
masm.convertInt32ValueToDouble(valueAddr, R0.scratchReg(), &convertDoublesDone);
masm.jump(&convertDoublesDone);
// Failure case - fail but first unstow R0 and R1
masm.bind(&failureUnstow);
EmitUnstowICValues(masm, 2);
@ -2181,13 +2195,27 @@ ICSetElem_DenseAdd::Compiler::generateStubCode(MacroAssembler &masm)
masm.add32(Imm32(1), length);
masm.bind(&skipIncrementLength);
// Convert int32 values to double if convertDoubleElements is set. In this
// case the heap typeset is guaranteed to contain both int32 and double, so
// it's okay to store a double.
Label convertDoubles, convertDoublesDone;
Address convertDoublesAddr(scratchReg, ObjectElements::offsetOfConvertDoubleElements());
masm.branch32(Assembler::NotEqual, convertDoublesAddr, Imm32(0), &convertDoubles);
masm.bind(&convertDoublesDone);
// Write the value. No need for write barrier since we're not overwriting an old value.
// It's safe to overwrite R0 now.
BaseIndex element(scratchReg, key, TimesEight);
masm.loadValue(Address(BaselineStackReg, ICStackValueOffset), R0);
Address valueAddr(BaselineStackReg, ICStackValueOffset);
masm.loadValue(valueAddr, R0);
masm.storeValue(R0, element);
EmitReturnFromIC(masm);
// Convert to double and jump back.
masm.bind(&convertDoubles);
masm.convertInt32ValueToDouble(valueAddr, R0.scratchReg(), &convertDoublesDone);
masm.jump(&convertDoublesDone);
// Failure case - fail but first unstow R0 and R1
masm.bind(&failureUnstow);
EmitUnstowICValues(masm, 2);

View File

@ -798,3 +798,12 @@ MacroAssembler::copyMem(Register copyFrom, Register copyEnd, Register copyTo, Re
jump(&copyLoop);
bind(&copyDone);
}
void
MacroAssembler::convertInt32ValueToDouble(const Address &address, Register scratch, Label *done)
{
branchTestInt32(Assembler::NotEqual, address, done);
unboxInt32(address, scratch);
convertInt32ToDouble(scratch, ScratchFloatReg);
storeDouble(ScratchFloatReg, address);
}

View File

@ -689,6 +689,7 @@ class MacroAssembler : public MacroAssemblerSpecific
void copyMem(Register copyFrom, Register copyEnd, Register copyTo, Register temp);
void convertInt32ValueToDouble(const Address &address, Register scratch, Label *done);
};
static inline Assembler::Condition

View File

@ -2223,6 +2223,15 @@ MacroAssemblerARMCompat::testMagic(Assembler::Condition cond, const BaseIndex &a
return cond;
}
Assembler::Condition
MacroAssemblerARMCompat::testInt32(Assembler::Condition cond, const Address &address)
{
JS_ASSERT(cond == Equal || cond == NotEqual);
extractTag(address, ScratchRegister);
ma_cmp(ScratchRegister, ImmTag(JSVAL_TAG_INT32));
return cond;
}
Assembler::Condition
MacroAssemblerARMCompat::testDouble(Condition cond, const Register &tag)
{

View File

@ -578,6 +578,7 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
Condition testGCThing(Condition cond, const BaseIndex &address);
Condition testMagic(Condition cond, const Address &address);
Condition testMagic(Condition cond, const BaseIndex &address);
Condition testInt32(Condition cond, const Address &address);
template <typename T>
void branchTestGCThing(Condition cond, const T &t, Label *label) {

View File

@ -602,6 +602,10 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
cmpl(ToUpper32(operand), Imm32(Upper32Of(GetShiftedTag(JSVAL_TYPE_INT32))));
j(cond, label);
}
void branchTestInt32(Condition cond, const Address &address, Label *label) {
JS_ASSERT(cond == Equal || cond == NotEqual);
branchTestInt32(cond, Operand(address), label);
}
void branchTestBoolean(Condition cond, const Operand &operand, Label *label) {
JS_ASSERT(cond == Equal || cond == NotEqual);
cmpl(ToUpper32(operand), Imm32(Upper32Of(GetShiftedTag(JSVAL_TYPE_BOOLEAN))));

View File

@ -303,6 +303,10 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
cmpl(ToType(operand), ImmTag(JSVAL_TAG_INT32));
return cond;
}
Condition testInt32(Condition cond, const Address &address) {
JS_ASSERT(cond == Equal || cond == NotEqual);
return testInt32(cond, Operand(address));
}
Condition testUndefined(Condition cond, const ValueOperand &value) {
return testUndefined(cond, value.typeReg());
}