mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1147430 - Optimize load followed by unbox. r=jandem
This commit is contained in:
parent
66f629325e
commit
9f160a3984
@ -8392,6 +8392,40 @@ CodeGenerator::visitLoadFixedSlotT(LLoadFixedSlotT* ins)
|
||||
masm.loadUnboxedValue(Address(obj, NativeObject::getFixedSlotOffset(slot)), type, result);
|
||||
}
|
||||
|
||||
void
|
||||
CodeGenerator::visitLoadFixedSlotAndUnbox(LLoadFixedSlotAndUnbox* ins)
|
||||
{
|
||||
const MLoadFixedSlotAndUnbox* mir = ins->mir();
|
||||
MIRType type = mir->type();
|
||||
const Register input = ToRegister(ins->getOperand(0));
|
||||
AnyRegister result = ToAnyRegister(ins->output());
|
||||
size_t slot = mir->slot();
|
||||
|
||||
Address address(input, NativeObject::getFixedSlotOffset(slot));
|
||||
Label bail;
|
||||
if (type == MIRType_Double) {
|
||||
MOZ_ASSERT(result.isFloat());
|
||||
masm.ensureDouble(address, result.fpu(), &bail);
|
||||
if (mir->fallible())
|
||||
bailoutFrom(&bail, ins->snapshot());
|
||||
return;
|
||||
}
|
||||
if (mir->fallible()) {
|
||||
switch (type) {
|
||||
case MIRType_Int32:
|
||||
masm.branchTestInt32(Assembler::NotEqual, address, &bail);
|
||||
break;
|
||||
case MIRType_Boolean:
|
||||
masm.branchTestBoolean(Assembler::NotEqual, address, &bail);
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("Given MIRType cannot be unboxed.");
|
||||
}
|
||||
bailoutFrom(&bail, ins->snapshot());
|
||||
}
|
||||
masm.loadUnboxedValue(address, type, result);
|
||||
}
|
||||
|
||||
void
|
||||
CodeGenerator::visitStoreFixedSlotV(LStoreFixedSlotV* ins)
|
||||
{
|
||||
|
@ -214,6 +214,7 @@ class CodeGenerator : public CodeGeneratorSpecific
|
||||
void visitBoundsCheckRange(LBoundsCheckRange* lir);
|
||||
void visitBoundsCheckLower(LBoundsCheckLower* lir);
|
||||
void visitLoadFixedSlotV(LLoadFixedSlotV* ins);
|
||||
void visitLoadFixedSlotAndUnbox(LLoadFixedSlotAndUnbox* lir);
|
||||
void visitLoadFixedSlotT(LLoadFixedSlotT* ins);
|
||||
void visitStoreFixedSlotV(LStoreFixedSlotV* ins);
|
||||
void visitStoreFixedSlotT(LStoreFixedSlotT* ins);
|
||||
|
@ -3206,6 +3206,19 @@ LIRGenerator::visitLoadFixedSlot(MLoadFixedSlot* ins)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LIRGenerator::visitLoadFixedSlotAndUnbox(MLoadFixedSlotAndUnbox* ins)
|
||||
{
|
||||
MDefinition* obj = ins->object();
|
||||
MOZ_ASSERT(obj->type() == MIRType_Object);
|
||||
|
||||
LLoadFixedSlotAndUnbox* lir = new(alloc()) LLoadFixedSlotAndUnbox(useRegisterAtStart(obj));
|
||||
if (ins->fallible())
|
||||
assignSnapshot(lir, ins->bailoutKind());
|
||||
|
||||
define(lir, ins);
|
||||
}
|
||||
|
||||
void
|
||||
LIRGenerator::visitStoreFixedSlot(MStoreFixedSlot* ins)
|
||||
{
|
||||
|
@ -177,6 +177,7 @@ class LIRGenerator : public LIRGeneratorSpecific
|
||||
void visitMaybeToDoubleElement(MMaybeToDoubleElement* ins);
|
||||
void visitMaybeCopyElementsForWrite(MMaybeCopyElementsForWrite* ins);
|
||||
void visitLoadSlot(MLoadSlot* ins);
|
||||
void visitLoadFixedSlotAndUnbox(MLoadFixedSlotAndUnbox* ins);
|
||||
void visitFunctionEnvironment(MFunctionEnvironment* ins);
|
||||
void visitInterruptCheck(MInterruptCheck* ins);
|
||||
void visitAsmJSInterruptCheck(MAsmJSInterruptCheck* ins);
|
||||
|
@ -1554,6 +1554,30 @@ MUnbox::printOpcode(GenericPrinter& out) const
|
||||
}
|
||||
}
|
||||
|
||||
MDefinition*
|
||||
MUnbox::foldsTo(TempAllocator &alloc)
|
||||
{
|
||||
if (!input()->isLoadFixedSlot())
|
||||
return this;
|
||||
MLoadFixedSlot* load = input()->toLoadFixedSlot();
|
||||
if (load->type() != MIRType_Value)
|
||||
return this;
|
||||
if (type() != MIRType_Boolean && !IsNumberType(type()))
|
||||
return this;
|
||||
// Only optimize if the load comes immediately before the unbox, so it's
|
||||
// safe to copy the load's dependency field.
|
||||
MInstructionIterator iter(load->block()->begin(load));
|
||||
++iter;
|
||||
if (*iter != this)
|
||||
return this;
|
||||
|
||||
MLoadFixedSlotAndUnbox* ins = MLoadFixedSlotAndUnbox::New(alloc, load->object(), load->slot(),
|
||||
mode(), type(), bailoutKind());
|
||||
// As GVN runs after the Alias Analysis, we have to set the dependency by hand
|
||||
ins->setDependency(load->dependency());
|
||||
return ins;
|
||||
}
|
||||
|
||||
void
|
||||
MTypeBarrier::printOpcode(GenericPrinter& out) const
|
||||
{
|
||||
@ -4159,6 +4183,14 @@ MLoadFixedSlot::mightAlias(const MDefinition* store) const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
MLoadFixedSlotAndUnbox::mightAlias(const MDefinition* store) const
|
||||
{
|
||||
if (store->isStoreFixedSlot() && store->toStoreFixedSlot()->slot() != slot())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
MDefinition*
|
||||
MLoadFixedSlot::foldsTo(TempAllocator& alloc)
|
||||
{
|
||||
|
@ -4449,6 +4449,9 @@ class MUnbox final : public MUnaryInstruction, public BoxInputsPolicy::Data
|
||||
return false;
|
||||
return congruentIfOperandsEqual(ins);
|
||||
}
|
||||
|
||||
MDefinition* foldsTo(TempAllocator& alloc) override;
|
||||
|
||||
AliasSet getAliasSet() const override {
|
||||
return AliasSet::None();
|
||||
}
|
||||
@ -10115,6 +10118,67 @@ class MLoadFixedSlot
|
||||
ALLOW_CLONE(MLoadFixedSlot)
|
||||
};
|
||||
|
||||
class MLoadFixedSlotAndUnbox
|
||||
: public MUnaryInstruction,
|
||||
public SingleObjectPolicy::Data
|
||||
{
|
||||
size_t slot_;
|
||||
MUnbox::Mode mode_;
|
||||
BailoutKind bailoutKind_;
|
||||
protected:
|
||||
MLoadFixedSlotAndUnbox(MDefinition* obj, size_t slot, MUnbox::Mode mode, MIRType type,
|
||||
BailoutKind kind)
|
||||
: MUnaryInstruction(obj), slot_(slot), mode_(mode), bailoutKind_(kind)
|
||||
{
|
||||
setResultType(type);
|
||||
setMovable();
|
||||
if (mode_ == MUnbox::TypeBarrier || mode_ == MUnbox::Fallible)
|
||||
setGuard();
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(LoadFixedSlotAndUnbox)
|
||||
|
||||
static MLoadFixedSlotAndUnbox* New(TempAllocator& alloc, MDefinition* obj, size_t slot,
|
||||
MUnbox::Mode mode, MIRType type, BailoutKind kind)
|
||||
{
|
||||
return new(alloc) MLoadFixedSlotAndUnbox(obj, slot, mode, type, kind);
|
||||
}
|
||||
|
||||
MDefinition* object() const {
|
||||
return getOperand(0);
|
||||
}
|
||||
size_t slot() const {
|
||||
return slot_;
|
||||
}
|
||||
MUnbox::Mode mode() const {
|
||||
return mode_;
|
||||
}
|
||||
BailoutKind bailoutKind() const {
|
||||
return bailoutKind_;
|
||||
}
|
||||
bool fallible() const {
|
||||
return mode_ != MUnbox::Infallible;
|
||||
}
|
||||
bool congruentTo(const MDefinition* ins) const override {
|
||||
if (!ins->isLoadFixedSlotAndUnbox() ||
|
||||
slot() != ins->toLoadFixedSlotAndUnbox()->slot() ||
|
||||
mode() != ins->toLoadFixedSlotAndUnbox()->mode())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return congruentIfOperandsEqual(ins);
|
||||
}
|
||||
|
||||
AliasSet getAliasSet() const override {
|
||||
return AliasSet::Load(AliasSet::FixedSlot);
|
||||
}
|
||||
|
||||
bool mightAlias(const MDefinition* store) const override;
|
||||
|
||||
ALLOW_CLONE(MLoadFixedSlotAndUnbox);
|
||||
};
|
||||
|
||||
class MStoreFixedSlot
|
||||
: public MBinaryInstruction,
|
||||
public MixPolicy<SingleObjectPolicy, NoFloatPolicy<1> >::Data
|
||||
|
@ -214,6 +214,7 @@ namespace jit {
|
||||
_(EffectiveAddress) \
|
||||
_(ClampToUint8) \
|
||||
_(LoadFixedSlot) \
|
||||
_(LoadFixedSlotAndUnbox) \
|
||||
_(StoreFixedSlot) \
|
||||
_(CallGetProperty) \
|
||||
_(GetNameCache) \
|
||||
|
@ -1394,6 +1394,14 @@ MacroAssemblerMIPSCompat:: branchTestBoolean(Condition cond, Register tag, Label
|
||||
ma_b(tag, ImmType(JSVAL_TYPE_BOOLEAN), label, cond);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssemblerMIPSCompat::branchTestBoolean(Condition cond, const Address& address, Label* label)
|
||||
{
|
||||
MOZ_ASSERT(cond == Equal || cond == NotEqual);
|
||||
extractTag(address, SecondScratchReg);
|
||||
ma_b(SecondScratchReg, ImmTag(JSVAL_TAG_BOOLEAN), label, cond);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssemblerMIPSCompat::branchTestBoolean(Condition cond, const BaseIndex& src, Label* label)
|
||||
{
|
||||
|
@ -402,6 +402,7 @@ class MacroAssemblerMIPSCompat : public MacroAssemblerMIPS
|
||||
|
||||
void branchTestBoolean(Condition cond, const ValueOperand& value, Label* label);
|
||||
void branchTestBoolean(Condition cond, Register tag, Label* label);
|
||||
void branchTestBoolean(Condition cond, const Address& address, Label* label);
|
||||
void branchTestBoolean(Condition cond, const BaseIndex& src, Label* label);
|
||||
|
||||
void branch32(Condition cond, Register lhs, Register rhs, Label* label) {
|
||||
|
@ -5508,6 +5508,20 @@ class LLoadFixedSlotT : public LInstructionHelper<1, 1, 0>
|
||||
}
|
||||
};
|
||||
|
||||
class LLoadFixedSlotAndUnbox : public LInstructionHelper<1, 1, 0>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(LoadFixedSlotAndUnbox)
|
||||
|
||||
explicit LLoadFixedSlotAndUnbox(const LAllocation& object) {
|
||||
setOperand(0, object);
|
||||
}
|
||||
|
||||
const MLoadFixedSlotAndUnbox* mir() const {
|
||||
return mir_->toLoadFixedSlotAndUnbox();
|
||||
}
|
||||
};
|
||||
|
||||
// Store a boxed value to an object's fixed slot.
|
||||
class LStoreFixedSlotV : public LInstructionHelper<0, 1 + BOX_PIECES, 0>
|
||||
{
|
||||
|
@ -267,6 +267,7 @@
|
||||
_(ClampVToUint8) \
|
||||
_(LoadFixedSlotV) \
|
||||
_(LoadFixedSlotT) \
|
||||
_(LoadFixedSlotAndUnbox) \
|
||||
_(StoreFixedSlotV) \
|
||||
_(StoreFixedSlotT) \
|
||||
_(FunctionEnvironment) \
|
||||
|
@ -953,6 +953,10 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
|
||||
cmp32(ToUpper32(operand), Imm32(Upper32Of(GetShiftedTag(JSVAL_TYPE_BOOLEAN))));
|
||||
j(cond, label);
|
||||
}
|
||||
void branchTestBoolean(Condition cond, const Address& address, Label* label) {
|
||||
MOZ_ASSERT(cond == Equal || cond == NotEqual);
|
||||
branchTestBoolean(cond, Operand(address), label);
|
||||
}
|
||||
void branchTestNull(Condition cond, const Operand& operand, Label* label) {
|
||||
MOZ_ASSERT(cond == Equal || cond == NotEqual);
|
||||
cmp32(ToUpper32(operand), Imm32(Upper32Of(GetShiftedTag(JSVAL_TYPE_NULL))));
|
||||
|
@ -353,6 +353,11 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
|
||||
Condition testError(Condition cond, Register tag) {
|
||||
return testMagic(cond, tag);
|
||||
}
|
||||
Condition testBoolean(Condition cond, const Address& address) {
|
||||
MOZ_ASSERT(cond == Equal || cond == NotEqual);
|
||||
cmp32(Operand(ToType(address)), ImmTag(JSVAL_TAG_BOOLEAN));
|
||||
return cond;
|
||||
}
|
||||
Condition testInt32(Condition cond, const Operand& operand) {
|
||||
MOZ_ASSERT(cond == Equal || cond == NotEqual);
|
||||
cmp32(ToType(operand), ImmTag(JSVAL_TAG_INT32));
|
||||
|
Loading…
Reference in New Issue
Block a user