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);
|
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
|
void
|
||||||
CodeGenerator::visitStoreFixedSlotV(LStoreFixedSlotV* ins)
|
CodeGenerator::visitStoreFixedSlotV(LStoreFixedSlotV* ins)
|
||||||
{
|
{
|
||||||
|
@ -214,6 +214,7 @@ class CodeGenerator : public CodeGeneratorSpecific
|
|||||||
void visitBoundsCheckRange(LBoundsCheckRange* lir);
|
void visitBoundsCheckRange(LBoundsCheckRange* lir);
|
||||||
void visitBoundsCheckLower(LBoundsCheckLower* lir);
|
void visitBoundsCheckLower(LBoundsCheckLower* lir);
|
||||||
void visitLoadFixedSlotV(LLoadFixedSlotV* ins);
|
void visitLoadFixedSlotV(LLoadFixedSlotV* ins);
|
||||||
|
void visitLoadFixedSlotAndUnbox(LLoadFixedSlotAndUnbox* lir);
|
||||||
void visitLoadFixedSlotT(LLoadFixedSlotT* ins);
|
void visitLoadFixedSlotT(LLoadFixedSlotT* ins);
|
||||||
void visitStoreFixedSlotV(LStoreFixedSlotV* ins);
|
void visitStoreFixedSlotV(LStoreFixedSlotV* ins);
|
||||||
void visitStoreFixedSlotT(LStoreFixedSlotT* 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
|
void
|
||||||
LIRGenerator::visitStoreFixedSlot(MStoreFixedSlot* ins)
|
LIRGenerator::visitStoreFixedSlot(MStoreFixedSlot* ins)
|
||||||
{
|
{
|
||||||
|
@ -177,6 +177,7 @@ class LIRGenerator : public LIRGeneratorSpecific
|
|||||||
void visitMaybeToDoubleElement(MMaybeToDoubleElement* ins);
|
void visitMaybeToDoubleElement(MMaybeToDoubleElement* ins);
|
||||||
void visitMaybeCopyElementsForWrite(MMaybeCopyElementsForWrite* ins);
|
void visitMaybeCopyElementsForWrite(MMaybeCopyElementsForWrite* ins);
|
||||||
void visitLoadSlot(MLoadSlot* ins);
|
void visitLoadSlot(MLoadSlot* ins);
|
||||||
|
void visitLoadFixedSlotAndUnbox(MLoadFixedSlotAndUnbox* ins);
|
||||||
void visitFunctionEnvironment(MFunctionEnvironment* ins);
|
void visitFunctionEnvironment(MFunctionEnvironment* ins);
|
||||||
void visitInterruptCheck(MInterruptCheck* ins);
|
void visitInterruptCheck(MInterruptCheck* ins);
|
||||||
void visitAsmJSInterruptCheck(MAsmJSInterruptCheck* 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
|
void
|
||||||
MTypeBarrier::printOpcode(GenericPrinter& out) const
|
MTypeBarrier::printOpcode(GenericPrinter& out) const
|
||||||
{
|
{
|
||||||
@ -4159,6 +4183,14 @@ MLoadFixedSlot::mightAlias(const MDefinition* store) const
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
MLoadFixedSlotAndUnbox::mightAlias(const MDefinition* store) const
|
||||||
|
{
|
||||||
|
if (store->isStoreFixedSlot() && store->toStoreFixedSlot()->slot() != slot())
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
MDefinition*
|
MDefinition*
|
||||||
MLoadFixedSlot::foldsTo(TempAllocator& alloc)
|
MLoadFixedSlot::foldsTo(TempAllocator& alloc)
|
||||||
{
|
{
|
||||||
|
@ -4449,6 +4449,9 @@ class MUnbox final : public MUnaryInstruction, public BoxInputsPolicy::Data
|
|||||||
return false;
|
return false;
|
||||||
return congruentIfOperandsEqual(ins);
|
return congruentIfOperandsEqual(ins);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MDefinition* foldsTo(TempAllocator& alloc) override;
|
||||||
|
|
||||||
AliasSet getAliasSet() const override {
|
AliasSet getAliasSet() const override {
|
||||||
return AliasSet::None();
|
return AliasSet::None();
|
||||||
}
|
}
|
||||||
@ -10115,6 +10118,67 @@ class MLoadFixedSlot
|
|||||||
ALLOW_CLONE(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
|
class MStoreFixedSlot
|
||||||
: public MBinaryInstruction,
|
: public MBinaryInstruction,
|
||||||
public MixPolicy<SingleObjectPolicy, NoFloatPolicy<1> >::Data
|
public MixPolicy<SingleObjectPolicy, NoFloatPolicy<1> >::Data
|
||||||
|
@ -214,6 +214,7 @@ namespace jit {
|
|||||||
_(EffectiveAddress) \
|
_(EffectiveAddress) \
|
||||||
_(ClampToUint8) \
|
_(ClampToUint8) \
|
||||||
_(LoadFixedSlot) \
|
_(LoadFixedSlot) \
|
||||||
|
_(LoadFixedSlotAndUnbox) \
|
||||||
_(StoreFixedSlot) \
|
_(StoreFixedSlot) \
|
||||||
_(CallGetProperty) \
|
_(CallGetProperty) \
|
||||||
_(GetNameCache) \
|
_(GetNameCache) \
|
||||||
|
@ -1394,6 +1394,14 @@ MacroAssemblerMIPSCompat:: branchTestBoolean(Condition cond, Register tag, Label
|
|||||||
ma_b(tag, ImmType(JSVAL_TYPE_BOOLEAN), label, cond);
|
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
|
void
|
||||||
MacroAssemblerMIPSCompat::branchTestBoolean(Condition cond, const BaseIndex& src, Label* label)
|
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, const ValueOperand& value, Label* label);
|
||||||
void branchTestBoolean(Condition cond, Register tag, 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 branchTestBoolean(Condition cond, const BaseIndex& src, Label* label);
|
||||||
|
|
||||||
void branch32(Condition cond, Register lhs, Register rhs, 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.
|
// Store a boxed value to an object's fixed slot.
|
||||||
class LStoreFixedSlotV : public LInstructionHelper<0, 1 + BOX_PIECES, 0>
|
class LStoreFixedSlotV : public LInstructionHelper<0, 1 + BOX_PIECES, 0>
|
||||||
{
|
{
|
||||||
|
@ -267,6 +267,7 @@
|
|||||||
_(ClampVToUint8) \
|
_(ClampVToUint8) \
|
||||||
_(LoadFixedSlotV) \
|
_(LoadFixedSlotV) \
|
||||||
_(LoadFixedSlotT) \
|
_(LoadFixedSlotT) \
|
||||||
|
_(LoadFixedSlotAndUnbox) \
|
||||||
_(StoreFixedSlotV) \
|
_(StoreFixedSlotV) \
|
||||||
_(StoreFixedSlotT) \
|
_(StoreFixedSlotT) \
|
||||||
_(FunctionEnvironment) \
|
_(FunctionEnvironment) \
|
||||||
|
@ -953,6 +953,10 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
|
|||||||
cmp32(ToUpper32(operand), Imm32(Upper32Of(GetShiftedTag(JSVAL_TYPE_BOOLEAN))));
|
cmp32(ToUpper32(operand), Imm32(Upper32Of(GetShiftedTag(JSVAL_TYPE_BOOLEAN))));
|
||||||
j(cond, label);
|
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) {
|
void branchTestNull(Condition cond, const Operand& operand, Label* label) {
|
||||||
MOZ_ASSERT(cond == Equal || cond == NotEqual);
|
MOZ_ASSERT(cond == Equal || cond == NotEqual);
|
||||||
cmp32(ToUpper32(operand), Imm32(Upper32Of(GetShiftedTag(JSVAL_TYPE_NULL))));
|
cmp32(ToUpper32(operand), Imm32(Upper32Of(GetShiftedTag(JSVAL_TYPE_NULL))));
|
||||||
|
@ -353,6 +353,11 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
|
|||||||
Condition testError(Condition cond, Register tag) {
|
Condition testError(Condition cond, Register tag) {
|
||||||
return testMagic(cond, 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) {
|
Condition testInt32(Condition cond, const Operand& operand) {
|
||||||
MOZ_ASSERT(cond == Equal || cond == NotEqual);
|
MOZ_ASSERT(cond == Equal || cond == NotEqual);
|
||||||
cmp32(ToType(operand), ImmTag(JSVAL_TAG_INT32));
|
cmp32(ToType(operand), ImmTag(JSVAL_TAG_INT32));
|
||||||
|
Loading…
Reference in New Issue
Block a user