Bug 991153: Split uses of temp allocations into explicit float32 and doubles (r=djvj)

This commit is contained in:
Marty Rosenberg 2014-06-25 12:54:33 -04:00
parent 10aa17972c
commit 9479a316d2
11 changed files with 132 additions and 51 deletions

View File

@ -7111,19 +7111,20 @@ CodeGenerator::addSetPropertyCache(LInstruction *ins, RegisterSet liveRegs, Regi
bool
CodeGenerator::addSetElementCache(LInstruction *ins, Register obj, Register unboxIndex,
Register temp, FloatRegister tempFloat, ValueOperand index,
Register temp, FloatRegister tempDouble,
FloatRegister tempFloat32, ValueOperand index,
ConstantOrRegister value, bool strict, bool guardHoles,
jsbytecode *profilerLeavePc)
{
switch (gen->info().executionMode()) {
case SequentialExecution: {
SetElementIC cache(obj, unboxIndex, temp, tempFloat, index, value, strict,
SetElementIC cache(obj, unboxIndex, temp, tempDouble, tempFloat32, index, value, strict,
guardHoles);
cache.setProfilerLeavePC(profilerLeavePc);
return addCache(ins, allocateCache(cache));
}
case ParallelExecution: {
SetElementParIC cache(obj, unboxIndex, temp, tempFloat, index, value, strict,
SetElementParIC cache(obj, unboxIndex, temp, tempDouble, tempFloat32, index, value, strict,
guardHoles);
cache.setProfilerLeavePC(profilerLeavePc);
return addCache(ins, allocateCache(cache));
@ -7283,11 +7284,12 @@ CodeGenerator::visitSetElementCacheV(LSetElementCacheV *ins)
Register obj = ToRegister(ins->object());
Register unboxIndex = ToTempUnboxRegister(ins->tempToUnboxIndex());
Register temp = ToRegister(ins->temp());
FloatRegister tempFloat = ToFloatRegister(ins->tempFloat());
FloatRegister tempDouble = ToFloatRegister(ins->tempDouble());
FloatRegister tempFloat32 = ToFloatRegister(ins->tempFloat32());
ValueOperand index = ToValue(ins, LSetElementCacheV::Index);
ConstantOrRegister value = TypedOrValueRegister(ToValue(ins, LSetElementCacheV::Value));
return addSetElementCache(ins, obj, unboxIndex, temp, tempFloat, index, value,
return addSetElementCache(ins, obj, unboxIndex, temp, tempDouble, tempFloat32, index, value,
ins->mir()->strict(), ins->mir()->guardHoles(),
ins->mir()->profilerLeavePc());
}
@ -7298,7 +7300,8 @@ CodeGenerator::visitSetElementCacheT(LSetElementCacheT *ins)
Register obj = ToRegister(ins->object());
Register unboxIndex = ToTempUnboxRegister(ins->tempToUnboxIndex());
Register temp = ToRegister(ins->temp());
FloatRegister tempFloat = ToFloatRegister(ins->tempFloat());
FloatRegister tempDouble = ToFloatRegister(ins->tempDouble());
FloatRegister tempFloat32 = ToFloatRegister(ins->tempFloat32());
ValueOperand index = ToValue(ins, LSetElementCacheT::Index);
ConstantOrRegister value;
const LAllocation *tmp = ins->value();
@ -7307,7 +7310,7 @@ CodeGenerator::visitSetElementCacheT(LSetElementCacheT *ins)
else
value = TypedOrValueRegister(ins->mir()->value()->type(), ToAnyRegister(tmp));
return addSetElementCache(ins, obj, unboxIndex, temp, tempFloat, index, value,
return addSetElementCache(ins, obj, unboxIndex, temp, tempDouble, tempFloat32, index, value,
ins->mir()->strict(), ins->mir()->guardHoles(),
ins->mir()->profilerLeavePc());
}
@ -8722,11 +8725,16 @@ CodeGenerator::visitAssertRangeF(LAssertRangeF *ins)
{
FloatRegister input = ToFloatRegister(ins->input());
FloatRegister temp = ToFloatRegister(ins->temp());
FloatRegister dest = input;
if (hasMultiAlias())
dest = ToFloatRegister(ins->armtemp());
const Range *r = ins->range();
masm.convertFloat32ToDouble(input, input);
bool success = emitAssertRangeD(r, input, temp);
masm.convertDoubleToFloat32(input, input);
masm.convertFloat32ToDouble(input, dest);
bool success = emitAssertRangeD(r, dest, temp);
if (dest == input)
masm.convertDoubleToFloat32(input, input);
return success;
}

View File

@ -369,7 +369,8 @@ class CodeGenerator : public CodeGeneratorSpecific
PropertyName *name, ConstantOrRegister value, bool strict,
bool needsTypeBarrier, jsbytecode *profilerLeavePc);
bool addSetElementCache(LInstruction *ins, Register obj, Register unboxIndex, Register temp,
FloatRegister tempFloat, ValueOperand index, ConstantOrRegister value,
FloatRegister tempDouble, FloatRegister tempFloat32,
ValueOperand index, ConstantOrRegister value,
bool strict, bool guardHoles, jsbytecode *profilerLeavePc);
bool generateBranchV(const ValueOperand &value, Label *ifTrue, Label *ifFalse, FloatRegister fr);

View File

@ -3702,7 +3702,8 @@ static bool
GenerateSetTypedArrayElement(JSContext *cx, MacroAssembler &masm, IonCache::StubAttacher &attacher,
HandleTypedArrayObject tarr, Register object,
ValueOperand indexVal, ConstantOrRegister value,
Register tempUnbox, Register temp, FloatRegister tempFloat)
Register tempUnbox, Register temp, FloatRegister tempDouble,
FloatRegister tempFloat32)
{
Label failures, done, popObjectAndFail;
@ -3731,18 +3732,22 @@ GenerateSetTypedArrayElement(JSContext *cx, MacroAssembler &masm, IonCache::Stub
BaseIndex target(elements, index, ScaleFromElemWidth(width));
if (arrayType == ScalarTypeDescr::TYPE_FLOAT32) {
FloatRegister ftemp;
if (LIRGenerator::allowFloat32Optimizations()) {
if (!masm.convertConstantOrRegisterToFloat(cx, value, tempFloat, &failures))
JS_ASSERT(tempFloat32 != InvalidFloatReg);
if (!masm.convertConstantOrRegisterToFloat(cx, value, tempFloat32, &failures))
return false;
ftemp = tempFloat32;
} else {
if (!masm.convertConstantOrRegisterToDouble(cx, value, tempFloat, &failures))
if (!masm.convertConstantOrRegisterToDouble(cx, value, tempDouble, &failures))
return false;
ftemp = tempDouble;
}
masm.storeToTypedFloatArray(arrayType, tempFloat, target);
masm.storeToTypedFloatArray(arrayType, ftemp, target);
} else if (arrayType == ScalarTypeDescr::TYPE_FLOAT64) {
if (!masm.convertConstantOrRegisterToDouble(cx, value, tempFloat, &failures))
if (!masm.convertConstantOrRegisterToDouble(cx, value, tempDouble, &failures))
return false;
masm.storeToTypedFloatArray(arrayType, tempFloat, target);
masm.storeToTypedFloatArray(arrayType, tempDouble, target);
} else {
// On x86 we only have 6 registers available to use, so reuse the object
// register to compute the intermediate value to store and restore it
@ -3750,13 +3755,13 @@ GenerateSetTypedArrayElement(JSContext *cx, MacroAssembler &masm, IonCache::Stub
masm.push(object);
if (arrayType == ScalarTypeDescr::TYPE_UINT8_CLAMPED) {
if (!masm.clampConstantOrRegisterToUint8(cx, value, tempFloat, object,
if (!masm.clampConstantOrRegisterToUint8(cx, value, tempDouble, object,
&popObjectAndFail))
{
return false;
}
} else {
if (!masm.truncateConstantOrRegisterToInt32(cx, value, tempFloat, object,
if (!masm.truncateConstantOrRegisterToInt32(cx, value, tempDouble, object,
&popObjectAndFail))
{
return false;
@ -3789,7 +3794,7 @@ SetElementIC::attachTypedArrayElement(JSContext *cx, HandleScript outerScript, I
RepatchStubAppender attacher(*this);
if (!GenerateSetTypedArrayElement(cx, masm, attacher, tarr,
object(), index(), value(),
tempToUnboxIndex(), temp(), tempFloat()))
tempToUnboxIndex(), temp(), tempDouble(), tempFloat32()))
{
return false;
}
@ -3860,7 +3865,7 @@ SetElementParIC::attachTypedArrayElement(LockedJSContext &cx, IonScript *ion,
DispatchStubPrepender attacher(*this);
if (!GenerateSetTypedArrayElement(cx, masm, attacher, tarr,
object(), index(), value(),
tempToUnboxIndex(), temp(), tempFloat()))
tempToUnboxIndex(), temp(), tempDouble(), tempFloat32()))
{
return false;
}

View File

@ -851,7 +851,8 @@ class SetElementIC : public RepatchIonCache
Register object_;
Register tempToUnboxIndex_;
Register temp_;
FloatRegister tempFloat_;
FloatRegister tempDouble_;
FloatRegister tempFloat32_;
ValueOperand index_;
ConstantOrRegister value_;
bool strict_;
@ -861,12 +862,14 @@ class SetElementIC : public RepatchIonCache
public:
SetElementIC(Register object, Register tempToUnboxIndex, Register temp,
FloatRegister tempFloat, ValueOperand index, ConstantOrRegister value,
FloatRegister tempDouble, FloatRegister tempFloat32,
ValueOperand index, ConstantOrRegister value,
bool strict, bool guardHoles)
: object_(object),
tempToUnboxIndex_(tempToUnboxIndex),
temp_(temp),
tempFloat_(tempFloat),
tempDouble_(tempDouble),
tempFloat32_(tempFloat32),
index_(index),
value_(value),
strict_(strict),
@ -888,8 +891,11 @@ class SetElementIC : public RepatchIonCache
Register temp() const {
return temp_;
}
FloatRegister tempFloat() const {
return tempFloat_;
FloatRegister tempDouble() const {
return tempDouble_;
}
FloatRegister tempFloat32() const {
return tempFloat32_;
}
ValueOperand index() const {
return index_;
@ -1247,7 +1253,8 @@ class SetElementParIC : public ParallelIonCache
Register object_;
Register tempToUnboxIndex_;
Register temp_;
FloatRegister tempFloat_;
FloatRegister tempDouble_;
FloatRegister tempFloat32_;
ValueOperand index_;
ConstantOrRegister value_;
bool strict_;
@ -1255,12 +1262,13 @@ class SetElementParIC : public ParallelIonCache
public:
SetElementParIC(Register object, Register tempToUnboxIndex, Register temp,
FloatRegister tempFloat, ValueOperand index, ConstantOrRegister value,
FloatRegister tempDouble, FloatRegister tempFloat32, ValueOperand index, ConstantOrRegister value,
bool strict, bool guardHoles)
: object_(object),
tempToUnboxIndex_(tempToUnboxIndex),
temp_(temp),
tempFloat_(tempFloat),
tempDouble_(tempDouble),
tempFloat32_(tempFloat32),
index_(index),
value_(value),
strict_(strict),
@ -1285,8 +1293,11 @@ class SetElementParIC : public ParallelIonCache
Register temp() const {
return temp_;
}
FloatRegister tempFloat() const {
return tempFloat_;
FloatRegister tempDouble() const {
return tempDouble_;
}
FloatRegister tempFloat32() const {
return tempFloat32_;
}
ValueOperand index() const {
return index_;

View File

@ -5091,7 +5091,7 @@ class LSetPropertyCacheT : public LInstructionHelper<0, 2, 2>
}
};
class LSetElementCacheV : public LInstructionHelper<0, 1 + 2 * BOX_PIECES, 3>
class LSetElementCacheV : public LInstructionHelper<0, 1 + 2 * BOX_PIECES, 4>
{
public:
LIR_HEADER(SetElementCacheV);
@ -5100,12 +5100,14 @@ class LSetElementCacheV : public LInstructionHelper<0, 1 + 2 * BOX_PIECES, 3>
static const size_t Value = 1 + BOX_PIECES;
LSetElementCacheV(const LAllocation &object, const LDefinition &tempToUnboxIndex,
const LDefinition &temp, const LDefinition &tempFloat)
const LDefinition &temp, const LDefinition &tempDouble,
const LDefinition &tempFloat32)
{
setOperand(0, object);
setTemp(0, tempToUnboxIndex);
setTemp(1, temp);
setTemp(2, tempFloat);
setTemp(2, tempDouble);
setTemp(3, tempFloat32);
}
const MSetElementCache *mir() const {
return mir_->toSetElementCache();
@ -5120,12 +5122,18 @@ class LSetElementCacheV : public LInstructionHelper<0, 1 + 2 * BOX_PIECES, 3>
const LDefinition *temp() {
return getTemp(1);
}
const LDefinition *tempFloat() {
const LDefinition *tempDouble() {
return getTemp(2);
}
const LDefinition *tempFloat32() {
if (hasUnaliasedDouble())
return getTemp(3);
return getTemp(2);
}
};
class LSetElementCacheT : public LInstructionHelper<0, 2 + BOX_PIECES, 3>
class LSetElementCacheT : public LInstructionHelper<0, 2 + BOX_PIECES, 4>
{
public:
LIR_HEADER(SetElementCacheT);
@ -5134,12 +5142,14 @@ class LSetElementCacheT : public LInstructionHelper<0, 2 + BOX_PIECES, 3>
LSetElementCacheT(const LAllocation &object, const LAllocation &value,
const LDefinition &tempToUnboxIndex,
const LDefinition &temp, const LDefinition &tempFloat) {
const LDefinition &temp, const LDefinition &tempDouble,
const LDefinition &tempFloat32) {
setOperand(0, object);
setOperand(1, value);
setTemp(0, tempToUnboxIndex);
setTemp(1, temp);
setTemp(2, tempFloat);
setTemp(2, tempDouble);
setTemp(3, tempFloat32);
}
const MSetElementCache *mir() const {
return mir_->toSetElementCache();
@ -5157,9 +5167,15 @@ class LSetElementCacheT : public LInstructionHelper<0, 2 + BOX_PIECES, 3>
const LDefinition *temp() {
return getTemp(1);
}
const LDefinition *tempFloat() {
const LDefinition *tempDouble() {
return getTemp(2);
}
const LDefinition *tempFloat32() {
if (hasUnaliasedDouble())
return getTemp(3);
return getTemp(2);
}
};
class LCallIteratorStart : public LCallInstructionHelper<1, 1, 0>
@ -6025,14 +6041,17 @@ class LAssertRangeD : public LInstructionHelper<0, 1, 1>
}
};
class LAssertRangeF : public LInstructionHelper<0, 1, 1>
class LAssertRangeF : public LInstructionHelper<0, 1, 2>
{
public:
LIR_HEADER(AssertRangeF)
LAssertRangeF(const LAllocation &input, const LDefinition &temp) {
LAssertRangeF(const LAllocation &input, const LDefinition &temp, const LDefinition &armtemp) {
setOperand(0, input);
setTemp(0, temp);
setTemp(1, armtemp);
}
const LDefinition *armtemp() {
return getTemp(1);
}
const LAllocation *input() {

View File

@ -1216,7 +1216,7 @@ LIRGenerator::visitRound(MRound *ins)
return define(lir, ins);
}
LRoundF *lir = new (alloc()) LRoundF(useRegister(ins->num()), tempDouble());
LRoundF *lir = new (alloc()) LRoundF(useRegister(ins->num()), tempFloat32());
if (!assignSnapshot(lir, Bailout_Round))
return false;
return define(lir, ins);
@ -3085,10 +3085,11 @@ LIRGenerator::visitAssertRange(MAssertRange *ins)
lir = new(alloc()) LAssertRangeD(useRegister(input), tempDouble());
break;
case MIRType_Float32:
lir = new(alloc()) LAssertRangeF(useRegister(input), tempFloat32());
case MIRType_Float32: {
LDefinition armtemp = hasMultiAlias() ? tempFloat32() : LDefinition::BogusTemp();
lir = new(alloc()) LAssertRangeF(useRegister(input), tempFloat32(), armtemp);
break;
}
case MIRType_Value:
lir = new(alloc()) LAssertRangeV(tempToUnbox(), tempDouble(), tempDouble());
if (!useBox(lir, LAssertRangeV::Input, input))
@ -3195,17 +3196,20 @@ LIRGenerator::visitSetElementCache(MSetElementCache *ins)
// |useRegister| below.
LInstruction *lir;
if (ins->value()->type() == MIRType_Value) {
LDefinition tempF32 = hasUnaliasedDouble() ? tempFloat32() : LDefinition::BogusTemp();
lir = new(alloc()) LSetElementCacheV(useByteOpRegister(ins->object()), tempToUnbox(),
temp(), tempDouble());
temp(), tempDouble(), tempF32);
if (!useBox(lir, LSetElementCacheV::Index, ins->index()))
return false;
if (!useBox(lir, LSetElementCacheV::Value, ins->value()))
return false;
} else {
LDefinition tempF32 = hasUnaliasedDouble() ? tempFloat32() : LDefinition::BogusTemp();
lir = new(alloc()) LSetElementCacheT(useByteOpRegister(ins->object()),
useRegisterOrConstant(ins->value()),
tempToUnbox(), temp(), tempDouble());
tempToUnbox(), temp(), tempDouble(),
tempF32);
if (!useBox(lir, LSetElementCacheT::Index, ins->index()))
return false;

View File

@ -398,9 +398,20 @@ uint32_t GetARMFlags();
bool HasMOVWT();
bool HasVFPv3();
bool HasVFP();
bool Has16DP();
bool Has32DP();
bool HasIDIV();
// Arm/D32 has double registers that can NOT be treated as float32
// and this requires some dances in lowering.
static bool hasUnaliasedDouble() {
return Has32DP();
}
// On ARM, Dn aliases both S2n and S2n+1, so if you need to convert a float32
// to a double as a temporary, you need a temporary double register.
static bool hasMultiAlias() {
return true;
}
bool ParseARMHwCapFlags(const char *armHwCap);
// If the simulator is used then the ABI choice is dynamic. Otherwise the ABI is static

View File

@ -215,6 +215,7 @@ class LIRGeneratorShared : public MInstructionVisitorWithDefaults
static bool allowInlineForkJoinGetSlice() {
return false;
}
};
} // namespace jit

View File

@ -191,6 +191,17 @@ struct FloatRegister {
bool aliases(FloatRegister const &other) const;
};
// Arm/D32 has double registers that can NOT be treated as float32
// and this requires some dances in lowering.
static bool hasUnaliasedDouble() {
return false;
}
// On ARM, Dn aliases both S2n and S2n+1, so if you need to convert a float32
// to a double as a temporary, you need a temporary double register.
static bool hasMultiAlias() {
return false;
}
} // namespace jit
} // namespace js

View File

@ -169,6 +169,18 @@ struct FloatRegister {
bool aliases(FloatRegister const &other) const;
};
// Arm/D32 has double registers that can NOT be treated as float32
// and this requires some dances in lowering.
static bool hasUnaliasedDouble() {
return false;
}
// On ARM, Dn aliases both S2n and S2n+1, so if you need to convert a float32
// to a double as a temporary, you need a temporary double register.
static bool hasMultiAlias() {
return false;
}
} // namespace jit
} // namespace js

View File

@ -64,11 +64,9 @@ class LIRGeneratorX86 : public LIRGeneratorX86Shared
static bool allowStaticTypedArrayAccesses() {
return true;
}
static bool allowFloat32Optimizations() {
return true;
}
static bool allowInlineForkJoinGetSlice() {
return true;
}