Bug 940525 - Fix Baseline typed array stubs to handle double indexes. r=djvj

This commit is contained in:
Jan de Mooij 2013-11-21 13:02:49 +01:00
parent 3af8ea7ca7
commit 2826a95d85

View File

@ -3881,7 +3881,7 @@ TryAttachGetElemStub(JSContext *cx, HandleScript script, jsbytecode *pc, ICGetEl
}
// Check for TypedArray[int] => Number accesses.
if (obj->is<TypedArrayObject>() && rhs.isInt32() && res.isNumber() &&
if (obj->is<TypedArrayObject>() && rhs.isNumber() && res.isNumber() &&
!TypedArrayGetElemStubExists(stub, obj))
{
// Don't attach CALLELEM stubs for accesses on typed array expected to yield numbers.
@ -3891,8 +3891,11 @@ TryAttachGetElemStub(JSContext *cx, HandleScript script, jsbytecode *pc, ICGetEl
#endif
Rooted<TypedArrayObject*> tarr(cx, &obj->as<TypedArrayObject>());
if (!cx->runtime()->jitSupportsFloatingPoint && TypedArrayRequiresFloatingPoint(tarr))
if (!cx->runtime()->jitSupportsFloatingPoint &&
(TypedArrayRequiresFloatingPoint(tarr) || rhs.isDouble()))
{
return true;
}
IonSpew(IonSpew_BaselineIC, " Generating GetElem(TypedArray[Int32]) stub");
ICGetElem_TypedArray::Compiler compiler(cx, tarr->lastProperty(), tarr->type());
@ -4502,7 +4505,6 @@ ICGetElem_TypedArray::Compiler::generateStubCode(MacroAssembler &masm)
{
Label failure;
masm.branchTestObject(Assembler::NotEqual, R0, &failure);
masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
GeneralRegisterSet regs(availableGeneralRegs(2));
Register scratchReg = regs.takeAny();
@ -4512,6 +4514,24 @@ ICGetElem_TypedArray::Compiler::generateStubCode(MacroAssembler &masm)
masm.loadPtr(Address(BaselineStubReg, ICGetElem_TypedArray::offsetOfShape()), scratchReg);
masm.branchTestObjShape(Assembler::NotEqual, obj, scratchReg, &failure);
// Ensure the index is an integer.
if (cx->runtime()->jitSupportsFloatingPoint) {
Label isInt32;
masm.branchTestInt32(Assembler::Equal, R1, &isInt32);
{
// If the index is a double, try to convert it to int32. It's okay
// to convert -0 to 0: the shape check ensures the object is a typed
// array so the difference is not observable.
masm.branchTestDouble(Assembler::NotEqual, R1, &failure);
masm.unboxDouble(R1, FloatReg0);
masm.convertDoubleToInt32(FloatReg0, scratchReg, &failure, /* negZeroCheck = */false);
masm.tagValue(JSVAL_TYPE_INT32, scratchReg, R1);
}
masm.bind(&isInt32);
} else {
masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
}
// Unbox key.
Register key = masm.extractInt32(R1, ExtractTemp1);
@ -4940,14 +4960,17 @@ DoSetElemFallback(JSContext *cx, BaselineFrame *frame, ICSetElem_Fallback *stub,
return true;
}
if (obj->is<TypedArrayObject>() && index.isInt32() && rhs.isNumber()) {
if (obj->is<TypedArrayObject>() && index.isNumber() && rhs.isNumber()) {
Rooted<TypedArrayObject*> tarr(cx, &obj->as<TypedArrayObject>());
if (!cx->runtime()->jitSupportsFloatingPoint && TypedArrayRequiresFloatingPoint(tarr))
if (!cx->runtime()->jitSupportsFloatingPoint &&
(TypedArrayRequiresFloatingPoint(tarr) || index.isDouble()))
{
return true;
}
uint32_t len = tarr->length();
int32_t idx = index.toInt32();
bool expectOutOfBounds = (idx < 0) || (static_cast<uint32_t>(idx) >= len);
double idx = index.toNumber();
bool expectOutOfBounds = (idx < 0 || idx >= double(len));
if (!TypedArraySetElemStubExists(stub, tarr, expectOutOfBounds)) {
// Remove any existing TypedArraySetElemStub that doesn't handle out-of-bounds
@ -5340,7 +5363,6 @@ ICSetElem_TypedArray::Compiler::generateStubCode(MacroAssembler &masm)
{
Label failure;
masm.branchTestObject(Assembler::NotEqual, R0, &failure);
masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
GeneralRegisterSet regs(availableGeneralRegs(2));
Register scratchReg = regs.takeAny();
@ -5350,6 +5372,24 @@ ICSetElem_TypedArray::Compiler::generateStubCode(MacroAssembler &masm)
masm.loadPtr(Address(BaselineStubReg, ICSetElem_TypedArray::offsetOfShape()), scratchReg);
masm.branchTestObjShape(Assembler::NotEqual, obj, scratchReg, &failure);
// Ensure the index is an integer.
if (cx->runtime()->jitSupportsFloatingPoint) {
Label isInt32;
masm.branchTestInt32(Assembler::Equal, R1, &isInt32);
{
// If the index is a double, try to convert it to int32. It's okay
// to convert -0 to 0: the shape check ensures the object is a typed
// array so the difference is not observable.
masm.branchTestDouble(Assembler::NotEqual, R1, &failure);
masm.unboxDouble(R1, FloatReg0);
masm.convertDoubleToInt32(FloatReg0, scratchReg, &failure, /* negZeroCheck = */false);
masm.tagValue(JSVAL_TYPE_INT32, scratchReg, R1);
}
masm.bind(&isInt32);
} else {
masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
}
// Unbox key.
Register key = masm.extractInt32(R1, ExtractTemp1);