[INFER] Disable inline paths for typed arrays on ARM and fix a regalloc problem, bug 663485. r=bhackett

This commit is contained in:
Jan de Mooij 2011-07-12 18:50:04 +02:00
parent 3164866fe0
commit 9444dd6946
7 changed files with 91 additions and 27 deletions

View File

@ -2736,7 +2736,7 @@ i?86-*)
ENABLE_METHODJIT=1
ENABLE_MONOIC=1
ENABLE_POLYIC=1
ENABLE_POLYIC_TYPED_ARRAY=1
ENABLE_METHODJIT_TYPED_ARRAY=1
AC_DEFINE(JS_CPU_X86)
AC_DEFINE(JS_NUNBOX32)
;;
@ -2746,7 +2746,7 @@ x86_64*-*)
ENABLE_METHODJIT=1
ENABLE_MONOIC=1
ENABLE_POLYIC=1
ENABLE_POLYIC_TYPED_ARRAY=1
ENABLE_METHODJIT_TYPED_ARRAY=1
AC_DEFINE(JS_CPU_X64)
AC_DEFINE(JS_PUNBOX64)
;;
@ -2765,7 +2765,7 @@ sparc*-*)
ENABLE_METHODJIT=1
ENABLE_MONOIC=1
ENABLE_POLYIC=1
ENABLE_POLYIC_TYPED_ARRAY=1
ENABLE_METHODJIT_TYPED_ARRAY=1
AC_DEFINE(JS_CPU_SPARC)
AC_DEFINE(JS_NUNBOX32)
;;
@ -2806,8 +2806,8 @@ if test "$ENABLE_POLYIC"; then
AC_DEFINE(JS_POLYIC)
fi
if test "$ENABLE_POLYIC_TYPED_ARRAY"; then
AC_DEFINE(JS_POLYIC_TYPED_ARRAY)
if test "$ENABLE_METHODJIT_TYPED_ARRAY"; then
AC_DEFINE(JS_METHODJIT_TYPED_ARRAY)
fi
if test "$ENABLE_METHODJIT_SPEW"; then

View File

@ -0,0 +1,30 @@
// Uint8Array and Int8Array need single byte registers.
// Test for id and value having the same backing.
function f() {
var x = new Uint8Array(30);
for (var i=0; i<x.length; i++) {
x[i] = i;
}
var res = 0;
for (var i=0; i<x.length; i++) {
res += x[i];
}
assertEq(res, 435);
}
f();
// Test for id and value having a different backing.
function g() {
var x = new Int8Array(30);
for (var i=1; i<x.length; i++) {
x[i-1] = i;
}
var res = 0;
for (var i=0; i<x.length; i++) {
res += x[i];
}
assertEq(res, 435);
}
g();

View File

@ -864,6 +864,7 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::SparcRegist
loadDynamicSlot(objReg, obj->dynamicSlotIndex(shape->slot), typeReg, dataReg);
}
#ifdef JS_METHODJIT_TYPED_ARRAY
// Load a value from a typed array's packed data vector into dataReg.
// This function expects the following combinations of typeReg, dataReg and tempReg:
// 1) for all INT arrays other than UINT32:
@ -1105,6 +1106,7 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::SparcRegist
done2.linkTo(label(), this);
done3.linkTo(label(), this);
}
#endif /* JS_METHODJIT_TYPED_ARRAY */
Address objPropAddress(JSObject *obj, RegisterID objReg, uint32 slot)
{

View File

@ -705,13 +705,17 @@ class Compiler : public BaseCompiler
void jsop_initprop();
void jsop_initelem();
void jsop_setelem_dense();
#ifdef JS_METHODJIT_TYPED_ARRAY
void jsop_setelem_typed(int atype);
void convertForTypedArray(int atype, ValueRemat *vr, bool *allocated);
#endif
bool jsop_setelem(bool popGuaranteed);
bool jsop_getelem(bool isCall);
void jsop_getelem_dense(bool isPacked);
void jsop_getelem_args();
#ifdef JS_METHODJIT_TYPED_ARRAY
void jsop_getelem_typed(int atype);
#endif
bool isCacheableBaseAndIndex(FrameEntry *obj, FrameEntry *id);
void jsop_stricteq(JSOp op);
bool jsop_equality(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused);

View File

@ -1194,6 +1194,7 @@ mjit::Compiler::jsop_setelem_dense()
stubcc.rejoin(Changes(2));
}
#ifdef JS_METHODJIT_TYPED_ARRAY
void
mjit::Compiler::convertForTypedArray(int atype, ValueRemat *vr, bool *allocated)
{
@ -1247,12 +1248,25 @@ mjit::Compiler::convertForTypedArray(int atype, ValueRemat *vr, bool *allocated)
* 2) For Uint8ClampedArray the register must be writable.
* 3) If the value is definitely int32 (and the array is not
* Uint8ClampedArray) we don't have to allocate a new register.
* 4) If id and value have the same backing (e.g. arr[i] = i) and
* we need a byte register, we have to allocate a new register
* because we've already pinned a key register and can't use
* tempRegInMaskForData.
*/
MaybeRegisterID reg;
bool needsByteReg = (atype == TypedArray::TYPE_INT8 ||
atype == TypedArray::TYPE_UINT8 ||
atype == TypedArray::TYPE_UINT8_CLAMPED);
if (!value->isType(JSVAL_TYPE_INT32) || atype == TypedArray::TYPE_UINT8_CLAMPED) {
FrameEntry *id = frame.peek(-2);
if (!value->isType(JSVAL_TYPE_INT32) || atype == TypedArray::TYPE_UINT8_CLAMPED ||
(needsByteReg && frame.haveSameBacking(id, value))) {
// Pin value so that we don't evict it.
MaybeRegisterID dataReg;
if (value->mightBeType(JSVAL_TYPE_INT32) && !frame.haveSameBacking(id, value)) {
dataReg = frame.tempRegForData(value);
frame.pinReg(dataReg.reg());
}
// x86 has 4 single byte registers. Worst case we've pinned 3
// registers, one for each of object, key and value. This means
// there must be at least one single byte register available.
@ -1261,6 +1275,8 @@ mjit::Compiler::convertForTypedArray(int atype, ValueRemat *vr, bool *allocated)
else
reg = frame.allocReg();
*allocated = true;
if (dataReg.isSet())
frame.unpinReg(dataReg.reg());
} else {
if (needsByteReg)
reg = frame.tempRegInMaskForData(value, Registers::SingleByteRegs).reg();
@ -1326,6 +1342,7 @@ mjit::Compiler::convertForTypedArray(int atype, ValueRemat *vr, bool *allocated)
}
}
}
void
mjit::Compiler::jsop_setelem_typed(int atype)
{
@ -1346,21 +1363,15 @@ mjit::Compiler::jsop_setelem_typed(int atype)
stubcc.linkExit(guard, Uses(3));
}
// Pin value. We don't use pinEntry here because it may also
// pin a type register and convertForTypedArray assumes we've
// pinned at most 3 registers (object, key and value).
MaybeRegisterID dataReg;
if (value->mightBeType(JSVAL_TYPE_INT32) && !value->isConstant()) {
dataReg = frame.tempRegForData(value);
frame.pinReg(dataReg.reg());
}
// Pin value.
ValueRemat vr;
frame.pinEntry(value, vr, /* breakDouble = */ false);
// Allocate and pin object and key regs.
Int32Key key = id->isConstant()
? Int32Key::FromConstant(id->getValue().toInt32())
: Int32Key::FromRegister(frame.tempRegForData(id));
JS_ASSERT_IF(frame.haveSameBacking(id, value), dataReg.isSet());
bool pinKey = !key.isConstant() && !frame.haveSameBacking(id, value);
if (pinKey)
frame.pinReg(key.reg());
@ -1377,12 +1388,19 @@ mjit::Compiler::jsop_setelem_typed(int atype)
// Load the array's packed data vector.
masm.loadPtr(Address(objReg, js::TypedArray::dataOffset()), objReg);
// Convert the value.
// Unpin value so that convertForTypedArray can assign a new data
// register using tempRegInMaskForData.
frame.unpinEntry(vr);
// Make sure key is pinned.
if (frame.haveSameBacking(id, value)) {
frame.pinReg(key.reg());
pinKey = true;
}
JS_ASSERT(pinKey == !id->isConstant());
bool allocated;
ValueRemat vr;
convertForTypedArray(atype, &vr, &allocated);
if (dataReg.isSet())
frame.unpinReg(dataReg.reg());
// Store the value.
masm.storeToTypedArray(atype, objReg, key, vr);
@ -1402,6 +1420,7 @@ mjit::Compiler::jsop_setelem_typed(int atype)
frame.shimmy(2);
stubcc.rejoin(Changes(2));
}
#endif /* JS_METHODJIT_TYPED_ARRAY */
bool
mjit::Compiler::jsop_setelem(bool popGuaranteed)
@ -1428,6 +1447,8 @@ mjit::Compiler::jsop_setelem(bool popGuaranteed)
jsop_setelem_dense();
return true;
}
#ifdef JS_METHODJIT_TYPED_ARRAY
if (!types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_TYPED_ARRAY) &&
(value->mightBeType(JSVAL_TYPE_INT32) || value->mightBeType(JSVAL_TYPE_DOUBLE))) {
// Inline typed array path. Look at the proto to determine the typed array type.
@ -1438,6 +1459,7 @@ mjit::Compiler::jsop_setelem(bool popGuaranteed)
return true;
}
}
#endif
}
SetElementICInfo ic = SetElementICInfo(JSOp(*PC));
@ -1814,6 +1836,7 @@ mjit::Compiler::jsop_getelem_args()
finishBarrier(barrier, REJOIN_FALLTHROUGH, 0);
}
#ifdef JS_METHODJIT_TYPED_ARRAY
void
mjit::Compiler::jsop_getelem_typed(int atype)
{
@ -1910,6 +1933,7 @@ mjit::Compiler::jsop_getelem_typed(int atype)
finishBarrier(barrier, REJOIN_FALLTHROUGH, 0);
}
#endif /* JS_METHODJIT_TYPED_ARRAY */
bool
mjit::Compiler::jsop_getelem(bool isCall)
@ -1934,6 +1958,7 @@ mjit::Compiler::jsop_getelem(bool isCall)
jsop_getelem_args();
return true;
}
if (obj->mightBeType(JSVAL_TYPE_OBJECT) &&
!types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_DENSE_ARRAY) &&
!arrayPrototypeHasIndexedProperty()) {
@ -1942,6 +1967,8 @@ mjit::Compiler::jsop_getelem(bool isCall)
jsop_getelem_dense(packed);
return true;
}
#ifdef JS_METHODJIT_TYPED_ARRAY
if (obj->mightBeType(JSVAL_TYPE_OBJECT) &&
!types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_TYPED_ARRAY)) {
// Inline typed array path. Look at the proto to determine the typed array type.
@ -1952,6 +1979,7 @@ mjit::Compiler::jsop_getelem(bool isCall)
return true;
}
}
#endif
}
frame.forgetMismatchedObject(obj);

View File

@ -2425,7 +2425,7 @@ GetElementIC::attachGetProp(VMFrame &f, JSContext *cx, JSObject *obj, const Valu
return Lookup_Cacheable;
}
#if defined JS_POLYIC_TYPED_ARRAY
#if defined JS_METHODJIT_TYPED_ARRAY
LookupStatus
GetElementIC::attachTypedArray(JSContext *cx, JSObject *obj, const Value &v, jsid id, Value *vp)
{
@ -2508,7 +2508,7 @@ GetElementIC::attachTypedArray(JSContext *cx, JSObject *obj, const Value &v, jsi
return Lookup_Cacheable;
}
#endif /* JS_POLYIC_TYPED_ARRAY */
#endif /* JS_METHODJIT_TYPED_ARRAY */
LookupStatus
GetElementIC::update(VMFrame &f, JSContext *cx, JSObject *obj, const Value &v, jsid id, Value *vp)
@ -2516,7 +2516,7 @@ GetElementIC::update(VMFrame &f, JSContext *cx, JSObject *obj, const Value &v, j
if (v.isString())
return attachGetProp(f, cx, obj, v, id, vp);
#if defined JS_POLYIC_TYPED_ARRAY
#if defined JS_METHODJIT_TYPED_ARRAY
/*
* Typed array ICs can make stub calls, and need to know which registers
* are in use and need to be restored after the call. If type inference is
@ -2783,7 +2783,7 @@ SetElementIC::attachHoleStub(JSContext *cx, JSObject *obj, int32 keyval)
return Lookup_Cacheable;
}
#if defined JS_POLYIC_TYPED_ARRAY
#if defined JS_METHODJIT_TYPED_ARRAY
LookupStatus
SetElementIC::attachTypedArray(JSContext *cx, JSObject *obj, int32 key)
{
@ -2871,7 +2871,7 @@ SetElementIC::attachTypedArray(JSContext *cx, JSObject *obj, int32 key)
return Lookup_Cacheable;
}
#endif /* JS_POLYIC_TYPED_ARRAY */
#endif /* JS_METHODJIT_TYPED_ARRAY */
LookupStatus
SetElementIC::update(JSContext *cx, const Value &objval, const Value &idval)
@ -2887,7 +2887,7 @@ SetElementIC::update(JSContext *cx, const Value &objval, const Value &idval)
if (obj->isDenseArray())
return attachHoleStub(cx, obj, key);
#if defined JS_POLYIC_TYPED_ARRAY
#if defined JS_METHODJIT_TYPED_ARRAY
/* Not attaching typed array stubs with linear scan allocator, see GetElementIC. */
if (!cx->typeInferenceEnabled() && js_IsTypedArray(obj))
return attachTypedArray(cx, obj, key);

View File

@ -49,7 +49,7 @@
namespace js {
namespace mjit {
#ifdef JS_POLYIC_TYPED_ARRAY
#ifdef JS_METHODJIT_TYPED_ARRAY
typedef JSC::MacroAssembler::RegisterID RegisterID;
typedef JSC::MacroAssembler::FPRegisterID FPRegisterID;
@ -430,7 +430,7 @@ StoreToTypedArray(JSContext *cx, Assembler &masm, js::TypedArray *tarray, T addr
return true;
}
#endif // defined(JS_POLYIC) && (defined JS_CPU_X86 || defined JS_CPU_X64)
#endif /* JS_METHODJIT_TYPED_ARRAY */
} /* namespace mjit */
} /* namespace js */