mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 907333 - IonMonkey: Add MAssertRange. r=h4writer
This commit is contained in:
parent
e4dd32b901
commit
cf6c6eadc6
@ -7274,11 +7274,8 @@ CodeGenerator::visitAsmJSCheckOverRecursed(LAsmJSCheckOverRecursed *lir)
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGenerator::visitRangeAssert(LRangeAssert *ins)
|
||||
CodeGenerator::emitAssertRangeI(Range *r, Register input)
|
||||
{
|
||||
Register input = ToRegister(ins->input());
|
||||
Range *r = ins->range();
|
||||
|
||||
// Check the lower bound.
|
||||
if (r->lower() != INT32_MIN) {
|
||||
Label success;
|
||||
@ -7303,12 +7300,8 @@ CodeGenerator::visitRangeAssert(LRangeAssert *ins)
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGenerator::visitDoubleRangeAssert(LDoubleRangeAssert *ins)
|
||||
CodeGenerator::emitAssertRangeD(Range *r, FloatRegister input, FloatRegister temp)
|
||||
{
|
||||
FloatRegister input = ToFloatRegister(ins->input());
|
||||
FloatRegister temp = ToFloatRegister(ins->temp());
|
||||
Range *r = ins->range();
|
||||
|
||||
// Check the lower bound.
|
||||
if (!r->isLowerInfinite()) {
|
||||
Label success;
|
||||
@ -7353,5 +7346,58 @@ CodeGenerator::visitDoubleRangeAssert(LDoubleRangeAssert *ins)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGenerator::visitAssertRangeI(LAssertRangeI *ins)
|
||||
{
|
||||
Register input = ToRegister(ins->input());
|
||||
Range *r = ins->range();
|
||||
|
||||
return emitAssertRangeI(r, input);
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGenerator::visitAssertRangeD(LAssertRangeD *ins)
|
||||
{
|
||||
FloatRegister input = ToFloatRegister(ins->input());
|
||||
FloatRegister temp = ToFloatRegister(ins->temp());
|
||||
Range *r = ins->range();
|
||||
|
||||
return emitAssertRangeD(r, input, temp);
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGenerator::visitAssertRangeV(LAssertRangeV *ins)
|
||||
{
|
||||
Range *r = ins->range();
|
||||
const ValueOperand value = ToValue(ins, LAssertRangeV::Input);
|
||||
Register tag = masm.splitTagForTest(value);
|
||||
Label done;
|
||||
|
||||
{
|
||||
Label isNotInt32;
|
||||
masm.branchTestInt32(Assembler::NotEqual, tag, &isNotInt32);
|
||||
Register unboxInt32 = ToTempUnboxRegister(ins->temp());
|
||||
Register input = masm.extractInt32(value, unboxInt32);
|
||||
emitAssertRangeI(r, input);
|
||||
masm.jump(&done);
|
||||
masm.bind(&isNotInt32);
|
||||
}
|
||||
|
||||
{
|
||||
Label isNotDouble;
|
||||
masm.branchTestDouble(Assembler::NotEqual, tag, &isNotDouble);
|
||||
FloatRegister input = ToFloatRegister(ins->floatTemp1());
|
||||
FloatRegister temp = ToFloatRegister(ins->floatTemp2());
|
||||
masm.unboxDouble(value, input);
|
||||
emitAssertRangeD(r, input, temp);
|
||||
masm.jump(&done);
|
||||
masm.bind(&isNotDouble);
|
||||
}
|
||||
|
||||
masm.breakpoint();
|
||||
masm.bind(&done);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace ion
|
||||
} // namespace js
|
||||
|
@ -301,8 +301,9 @@ class CodeGenerator : public CodeGeneratorSpecific
|
||||
bool visitNameIC(OutOfLineUpdateCache *ool, NameIC *ic);
|
||||
bool visitCallsiteCloneIC(OutOfLineUpdateCache *ool, CallsiteCloneIC *ic);
|
||||
|
||||
bool visitRangeAssert(LRangeAssert *ins);
|
||||
bool visitDoubleRangeAssert(LDoubleRangeAssert *ins);
|
||||
bool visitAssertRangeI(LAssertRangeI *ins);
|
||||
bool visitAssertRangeD(LAssertRangeD *ins);
|
||||
bool visitAssertRangeV(LAssertRangeV *ins);
|
||||
|
||||
IonScriptCounts *extractUnassociatedScriptCounts() {
|
||||
IonScriptCounts *counts = unassociatedScriptCounts_;
|
||||
@ -354,6 +355,9 @@ class CodeGenerator : public CodeGeneratorSpecific
|
||||
// Bailout if an element about to be written to is a hole.
|
||||
bool emitStoreHoleCheck(Register elements, const LAllocation *index, LSnapshot *snapshot);
|
||||
|
||||
bool emitAssertRangeI(Range *r, Register input);
|
||||
bool emitAssertRangeD(Range *r, FloatRegister input, FloatRegister temp);
|
||||
|
||||
// Script counts created when compiling code with no associated JSScript.
|
||||
IonScriptCounts *unassociatedScriptCounts_;
|
||||
|
||||
|
@ -1331,7 +1331,7 @@ OptimizeMIR(MIRGenerator *mir)
|
||||
if (mir->shouldCancel("RA Beta"))
|
||||
return false;
|
||||
|
||||
if (!r.analyze())
|
||||
if (!r.analyze() || !r.addRangeAssertions())
|
||||
return false;
|
||||
IonSpewPass("Range Analysis");
|
||||
AssertExtendedGraphCoherency(graph);
|
||||
|
@ -4923,16 +4923,12 @@ class LAsmJSCheckOverRecursed : public LInstructionHelper<0, 0, 0>
|
||||
}
|
||||
};
|
||||
|
||||
class LRangeAssert : public LInstructionHelper<0, 1, 0>
|
||||
class LAssertRangeI : public LInstructionHelper<0, 1, 0>
|
||||
{
|
||||
Range range_;
|
||||
|
||||
public:
|
||||
LIR_HEADER(RangeAssert)
|
||||
LIR_HEADER(AssertRangeI)
|
||||
|
||||
LRangeAssert(const LAllocation &input, Range r)
|
||||
: range_(r)
|
||||
{
|
||||
LAssertRangeI(const LAllocation &input) {
|
||||
setOperand(0, input);
|
||||
}
|
||||
|
||||
@ -4940,21 +4936,20 @@ class LRangeAssert : public LInstructionHelper<0, 1, 0>
|
||||
return getOperand(0);
|
||||
}
|
||||
|
||||
MAssertRange *mir() {
|
||||
return mir_->toAssertRange();
|
||||
}
|
||||
Range *range() {
|
||||
return &range_;
|
||||
return mir()->range();
|
||||
}
|
||||
};
|
||||
|
||||
class LDoubleRangeAssert : public LInstructionHelper<0, 1, 1>
|
||||
class LAssertRangeD : public LInstructionHelper<0, 1, 1>
|
||||
{
|
||||
Range range_;
|
||||
|
||||
public:
|
||||
LIR_HEADER(DoubleRangeAssert)
|
||||
LIR_HEADER(AssertRangeD)
|
||||
|
||||
LDoubleRangeAssert(const LAllocation &input, const LDefinition &temp, Range r)
|
||||
: range_(r)
|
||||
{
|
||||
LAssertRangeD(const LAllocation &input, const LDefinition &temp) {
|
||||
setOperand(0, input);
|
||||
setTemp(0, temp);
|
||||
}
|
||||
@ -4967,8 +4962,44 @@ class LDoubleRangeAssert : public LInstructionHelper<0, 1, 1>
|
||||
return getTemp(0);
|
||||
}
|
||||
|
||||
MAssertRange *mir() {
|
||||
return mir_->toAssertRange();
|
||||
}
|
||||
Range *range() {
|
||||
return &range_;
|
||||
return mir()->range();
|
||||
}
|
||||
};
|
||||
|
||||
class LAssertRangeV : public LInstructionHelper<0, BOX_PIECES, 3>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(AssertRangeV)
|
||||
|
||||
LAssertRangeV(const LDefinition &temp, const LDefinition &floatTemp1,
|
||||
const LDefinition &floatTemp2)
|
||||
{
|
||||
setTemp(0, temp);
|
||||
setTemp(1, floatTemp1);
|
||||
setTemp(2, floatTemp2);
|
||||
}
|
||||
|
||||
static const size_t Input = 0;
|
||||
|
||||
const LDefinition *temp() {
|
||||
return getTemp(0);
|
||||
}
|
||||
const LDefinition *floatTemp1() {
|
||||
return getTemp(1);
|
||||
}
|
||||
const LDefinition *floatTemp2() {
|
||||
return getTemp(2);
|
||||
}
|
||||
|
||||
MAssertRange *mir() {
|
||||
return mir_->toAssertRange();
|
||||
}
|
||||
Range *range() {
|
||||
return mir()->range();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -245,8 +245,9 @@
|
||||
_(AsmJSCall) \
|
||||
_(AsmJSCheckOverRecursed) \
|
||||
_(CheckInterruptPar) \
|
||||
_(RangeAssert) \
|
||||
_(DoubleRangeAssert)
|
||||
_(AssertRangeI) \
|
||||
_(AssertRangeD) \
|
||||
_(AssertRangeV)
|
||||
|
||||
#if defined(JS_CPU_X86)
|
||||
# include "jit/x86/LOpcodes-x86.h"
|
||||
|
@ -2447,6 +2447,36 @@ LIRGenerator::visitGuardString(MGuardString *ins)
|
||||
return redefine(ins, ins->input());
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGenerator::visitAssertRange(MAssertRange *ins)
|
||||
{
|
||||
MDefinition *input = ins->input();
|
||||
LInstruction *lir = NULL;
|
||||
|
||||
switch (input->type()) {
|
||||
case MIRType_Int32:
|
||||
lir = new LAssertRangeI(useRegisterAtStart(input));
|
||||
break;
|
||||
|
||||
case MIRType_Double:
|
||||
lir = new LAssertRangeD(useRegister(input), tempFloat());
|
||||
break;
|
||||
|
||||
case MIRType_Value:
|
||||
lir = new LAssertRangeV(tempToUnbox(), tempFloat(), tempFloat());
|
||||
if (!useBox(lir, LAssertRangeV::Input, input))
|
||||
return false;
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_ASSUME_UNREACHABLE("Unexpected Range for MIRType");
|
||||
break;
|
||||
}
|
||||
|
||||
lir->setMir(ins);
|
||||
return add(lir);
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGenerator::visitCallGetProperty(MCallGetProperty *ins)
|
||||
{
|
||||
@ -2935,25 +2965,6 @@ LIRGenerator::visitInstruction(MInstruction *ins)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check the computed range for this instruction, if the option is set. Note
|
||||
// that this code is quite invasive; it adds numerous additional
|
||||
// instructions for each MInstruction with a computed range, and it uses
|
||||
// registers, so it also affects register allocation.
|
||||
if (js_IonOptions.checkRangeAnalysis) {
|
||||
if (Range *r = ins->range()) {
|
||||
switch (ins->type()) {
|
||||
case MIRType_Int32:
|
||||
add(new LRangeAssert(useRegisterAtStart(ins), *r));
|
||||
break;
|
||||
case MIRType_Double:
|
||||
add(new LDoubleRangeAssert(useRegister(ins), tempFloat(), *r));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -206,6 +206,7 @@ class LIRGenerator : public LIRGeneratorSpecific
|
||||
bool visitGuardClass(MGuardClass *ins);
|
||||
bool visitGuardObject(MGuardObject *ins);
|
||||
bool visitGuardString(MGuardString *ins);
|
||||
bool visitAssertRange(MAssertRange *ins);
|
||||
bool visitCallGetProperty(MCallGetProperty *ins);
|
||||
bool visitDeleteProperty(MDeleteProperty *ins);
|
||||
bool visitGetNameCache(MGetNameCache *ins);
|
||||
|
@ -2227,6 +2227,29 @@ class MGuardString
|
||||
}
|
||||
};
|
||||
|
||||
class MAssertRange
|
||||
: public MUnaryInstruction
|
||||
{
|
||||
MAssertRange(MDefinition *ins)
|
||||
: MUnaryInstruction(ins)
|
||||
{
|
||||
setGuard();
|
||||
setMovable();
|
||||
setResultType(MIRType_None);
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(AssertRange)
|
||||
|
||||
static MAssertRange *New(MDefinition *ins) {
|
||||
return new MAssertRange(ins);
|
||||
}
|
||||
|
||||
AliasSet getAliasSet() const {
|
||||
return AliasSet::None();
|
||||
}
|
||||
};
|
||||
|
||||
// Caller-side allocation of |this| for |new|:
|
||||
// Given a templateobject, construct |this| for JSOP_NEW
|
||||
class MCreateThisWithTemplate
|
||||
|
@ -74,6 +74,7 @@ namespace ion {
|
||||
_(Unbox) \
|
||||
_(GuardObject) \
|
||||
_(GuardString) \
|
||||
_(AssertRange) \
|
||||
_(ToDouble) \
|
||||
_(ToInt32) \
|
||||
_(TruncateToInt32) \
|
||||
|
@ -200,6 +200,7 @@ class ParallelSafetyVisitor : public MInstructionVisitor
|
||||
SAFE_OP(GuardShape)
|
||||
SAFE_OP(GuardObjectType)
|
||||
SAFE_OP(GuardClass)
|
||||
SAFE_OP(AssertRange)
|
||||
SAFE_OP(ArrayLength)
|
||||
SAFE_OP(TypedArrayLength)
|
||||
SAFE_OP(TypedArrayElements)
|
||||
|
@ -1612,6 +1612,35 @@ RangeAnalysis::analyze()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
RangeAnalysis::addRangeAssertions()
|
||||
{
|
||||
if (!js_IonOptions.checkRangeAnalysis)
|
||||
return true;
|
||||
|
||||
// Check the computed range for this instruction, if the option is set. Note
|
||||
// that this code is quite invasive; it adds numerous additional
|
||||
// instructions for each MInstruction with a computed range, and it uses
|
||||
// registers, so it also affects register allocation.
|
||||
for (ReversePostorderIterator iter(graph_.rpoBegin()); iter != graph_.rpoEnd(); iter++) {
|
||||
MBasicBlock *block = *iter;
|
||||
|
||||
for (MInstructionIterator iter(block->begin()); iter != block->end(); iter++) {
|
||||
MInstruction *ins = *iter;
|
||||
|
||||
Range *r = ins->range();
|
||||
if (!r || ins->isAssertRange() || ins->isBeta())
|
||||
continue;
|
||||
|
||||
MAssertRange *guard = MAssertRange::New(ins);
|
||||
guard->setRange(new Range(*r));
|
||||
block->insertAfter(ins, guard);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Range based Truncation
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -81,6 +81,7 @@ class RangeAnalysis
|
||||
graph_(graph) {}
|
||||
bool addBetaNobes();
|
||||
bool analyze();
|
||||
bool addRangeAssertions();
|
||||
bool removeBetaNobes();
|
||||
bool truncate();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user