mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
[INFER] Disable inline paths for typed arrays on ARM and fix a regalloc problem, bug 663485. r=bhackett
This commit is contained in:
parent
3164866fe0
commit
9444dd6946
@ -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
|
||||
|
30
js/src/jit-test/tests/basic/testTypedArrayByteRegs.js
Normal file
30
js/src/jit-test/tests/basic/testTypedArrayByteRegs.js
Normal 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();
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user