Bug 1147430 - Optimize load followed by unbox. r=jandem

This commit is contained in:
Johannes Schulte 2015-11-15 20:41:47 +01:00
parent 66f629325e
commit 9f160a3984
13 changed files with 179 additions and 0 deletions

View File

@ -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)
{

View File

@ -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);

View File

@ -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)
{

View File

@ -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);

View File

@ -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)
{

View File

@ -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

View File

@ -214,6 +214,7 @@ namespace jit {
_(EffectiveAddress) \
_(ClampToUint8) \
_(LoadFixedSlot) \
_(LoadFixedSlotAndUnbox) \
_(StoreFixedSlot) \
_(CallGetProperty) \
_(GetNameCache) \

View File

@ -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)
{

View File

@ -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) {

View File

@ -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>
{

View File

@ -267,6 +267,7 @@
_(ClampVToUint8) \
_(LoadFixedSlotV) \
_(LoadFixedSlotT) \
_(LoadFixedSlotAndUnbox) \
_(StoreFixedSlotV) \
_(StoreFixedSlotT) \
_(FunctionEnvironment) \

View File

@ -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))));

View File

@ -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));