Bug 840696 part 2 - IonMonkey: Add typed array support to GetElem ICs. r=dvander

This commit is contained in:
Nicolas B. Pierron 2013-02-19 16:35:05 -08:00
parent ce8b68e312
commit 8e37d7ec25
2 changed files with 79 additions and 0 deletions

View File

@ -1596,6 +1596,80 @@ GetElementIC::attachDenseElement(JSContext *cx, IonScript *ion, JSObject *obj, c
return linkAndAttachStub(cx, masm, ion, "dense array", rejoinOffset, &exitOffset);
}
bool
GetElementIC::attachTypedArrayElement(JSContext *cx, IonScript *ion, JSObject *obj,
const Value &idval)
{
JS_ASSERT(obj->isTypedArray());
JS_ASSERT(idval.isInt32());
Label failures;
MacroAssembler masm;
// The array type is the object within the table of typed array classes.
int arrayType = obj->getClass() - &TypedArray::classes[0];
Register tmpReg;
if (output().hasValue()) {
tmpReg = output().valueReg().scratchReg();
} else {
JS_ASSERT(output().type() == MIRType_Int32);
tmpReg = output().typedReg().gpr();
}
JS_ASSERT(object() != tmpReg);
// Check that the typed array is of the same type as the current object
// because load size differ in function of the typed array data width.
masm.branchTestObjClass(Assembler::NotEqual, object(), tmpReg, obj->getClass(), &failures);
// Ensure the index is an int32 value.
ValueOperand val = index().reg().valueReg();
masm.branchTestInt32(Assembler::NotEqual, val, &failures);
// Unbox the index.
Register indexReg = tmpReg;
masm.unboxInt32(val, indexReg);
// Guard on the initialized length.
Address length(object(), TypedArray::lengthOffset());
masm.branch32(Assembler::BelowOrEqual, length, indexReg, &failures);
// Save the object register on the stack in case of failure.
Label popAndFail;
Register elementReg = object();
masm.push(object());
// Load elements vector.
masm.loadPtr(Address(object(), TypedArray::dataOffset()), elementReg);
// Load the value. We use an invalid register because the destination
// register is necessary a non double register.
int width = TypedArray::slotWidth(arrayType);
BaseIndex source(elementReg, indexReg, ScaleFromElemWidth(width));
if (output().hasValue())
masm.loadFromTypedArray(arrayType, source, output().valueReg(), true,
elementReg, &popAndFail);
else
masm.loadFromTypedArray(arrayType, source, output().typedReg(),
elementReg, &popAndFail);
masm.pop(object());
RepatchLabel rejoin_;
CodeOffsetJump rejoinOffset = masm.jumpWithPatch(&rejoin_);
masm.bind(&rejoin_);
// Restore the object before continuing to the next stub.
masm.bind(&popAndFail);
masm.pop(object());
masm.bind(&failures);
RepatchLabel exit_;
CodeOffsetJump exitOffset = masm.jumpWithPatch(&exit_);
masm.bind(&exit_);
return linkAndAttachStub(cx, masm, ion, "typed array", rejoinOffset, &exitOffset);
}
bool
GetElementIC::update(JSContext *cx, size_t cacheIndex, HandleObject obj,
HandleValue idval, MutableHandleValue res)
@ -1636,6 +1710,10 @@ GetElementIC::update(JSContext *cx, size_t cacheIndex, HandleObject obj,
if (!cache.attachDenseElement(cx, ion, obj, idval))
return false;
attachedStub = true;
} else if (obj->isTypedArray() && idval.isInt32()) {
if (!cache.attachTypedArrayElement(cx, ion, obj, idval))
return false;
attachedStub = true;
}
}

View File

@ -449,6 +449,7 @@ class GetElementIC : public IonCache
bool attachGetProp(JSContext *cx, IonScript *ion, HandleObject obj, const Value &idval, HandlePropertyName name);
bool attachDenseElement(JSContext *cx, IonScript *ion, JSObject *obj, const Value &idval);
bool attachTypedArrayElement(JSContext *cx, IonScript *ion, JSObject *obj, const Value &idval);
static bool
update(JSContext *cx, size_t cacheIndex, HandleObject obj, HandleValue idval,