Split MGenericSetProperty into two instructions (bug 725067 part 1, r=jandem).
authorDavid Anderson <danderson@mozilla.com>
Thu, 09 Feb 2012 11:59:05 -0800
changeset 112675 9cd94217ee4f5652e989d89b8911cf1418c57543
parent 112674 a32462495d865e9d05fa5c0b3b939e4384ba982f
child 112676 d546f1b141b9aec40b057d20d4d8dc8609d15e72
push id239
push userakeybl@mozilla.com
push dateThu, 03 Jan 2013 21:54:43 +0000
treeherdermozilla-release@3a7b66445659 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs725067
milestone13.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Split MGenericSetProperty into two instructions (bug 725067 part 1, r=jandem).
js/src/ion/CodeGenerator.cpp
js/src/ion/CodeGenerator.h
js/src/ion/IonBuilder.cpp
js/src/ion/LIR-Common.h
js/src/ion/LOpcodes.h
js/src/ion/Lowering.cpp
js/src/ion/Lowering.h
js/src/ion/MIR.h
js/src/ion/MOpcodes.h
--- a/js/src/ion/CodeGenerator.cpp
+++ b/js/src/ion/CodeGenerator.cpp
@@ -1649,53 +1649,48 @@ CodeGenerator::visitOutOfLineCacheGetPro
 
     return true;
 }
 
 ConstantOrRegister
 CodeGenerator::getSetPropertyValue(LInstruction *ins)
 {
     if (ins->getOperand(1)->isConstant()) {
-        JS_ASSERT(ins->isCallSetPropertyT() || ins->isCacheSetPropertyT());
+        JS_ASSERT(ins->isCacheSetPropertyT());
         return ConstantOrRegister(*ins->getOperand(1)->toConstant());
     }
 
     switch (ins->op()) {
-      case LInstruction::LOp_CallSetPropertyV:
-        return TypedOrValueRegister(ToValue(ins, LCallSetPropertyV::Value));
+      case LInstruction::LOp_CallSetProperty:
+        return TypedOrValueRegister(ToValue(ins, LCallSetProperty::Value));
       case LInstruction::LOp_CacheSetPropertyV:
         return TypedOrValueRegister(ToValue(ins, LCacheSetPropertyV::Value));
-      case LInstruction::LOp_CallSetPropertyT: {
-        LCallSetPropertyT *ins_ = ins->toCallSetPropertyT();
-        return TypedOrValueRegister(ins_->valueType(), ToAnyRegister(ins->getOperand(1)));
-      }
       case LInstruction::LOp_CacheSetPropertyT: {
         LCacheSetPropertyT *ins_ = ins->toCacheSetPropertyT();
         return TypedOrValueRegister(ins_->valueType(), ToAnyRegister(ins->getOperand(1)));
       }
       default:
         JS_NOT_REACHED("Bad opcode");
         return ConstantOrRegister(UndefinedValue());
     }
 }
 
 bool
-CodeGenerator::visitCallSetProperty(LInstruction *ins)
+CodeGenerator::visitCallSetProperty(LCallSetProperty *ins)
 {
     ConstantOrRegister value = getSetPropertyValue(ins);
-    const MGenericSetProperty *mir = ins->mirRaw()->toGenericSetProperty();
 
     const Register objReg = ToRegister(ins->getOperand(0));
 
     pushArg(value);
-    pushArg(ImmGCPtr(mir->atom()));
+    pushArg(ImmGCPtr(ins->mir()->atom()));
     pushArg(objReg);
 
     typedef bool (*pf)(JSContext *, JSObject *, JSAtom *, Value);
-    if (mir->strict()) {
+    if (ins->mir()->strict()) {
         static const VMFunction info = FunctionInfo<pf>(SetProperty<true>);
         if (!callVM(info, ins))
             return false;
     } else {
         static const VMFunction info = FunctionInfo<pf>(SetProperty<false>);
         if (!callVM(info, ins))
             return false;
     }
@@ -1707,17 +1702,17 @@ bool
 CodeGenerator::visitOutOfLineCacheSetProperty(OutOfLineCache *ool)
 {
     LInstruction *ins = ool->cache();
 
     Register objReg = ToRegister(ins->getOperand(0));
     RegisterSet liveRegs = ins->safepoint()->liveRegs();
 
     ConstantOrRegister value = getSetPropertyValue(ins);
-    const MGenericSetProperty *mir = ins->mirRaw()->toGenericSetProperty();
+    const MSetPropertyCache *mir = ins->mirRaw()->toSetPropertyCache();
 
     IonCacheSetProperty cache(ool->getInlineJump(), ool->getInlineLabel(),
                               masm.labelForPatch(), liveRegs,
                               objReg, mir->atom(), value,
                               mir->strict());
 
     size_t cacheIndex = allocateCache(cache);
 
--- a/js/src/ion/CodeGenerator.h
+++ b/js/src/ion/CodeGenerator.h
@@ -126,16 +126,17 @@ class CodeGenerator : public CodeGenerat
     bool visitStoreElementT(LStoreElementT *lir);
     bool visitStoreElementV(LStoreElementV *lir);
     bool visitStoreElementHoleT(LStoreElementHoleT *lir);
     bool visitStoreElementHoleV(LStoreElementHoleV *lir);
     bool visitCallIteratorStart(LCallIteratorStart *lir);
     bool visitCallIteratorNext(LCallIteratorNext *lir);
     bool visitCallIteratorMore(LCallIteratorMore *lir);
     bool visitCallIteratorEnd(LCallIteratorEnd *lir);
+    bool visitCallSetProperty(LCallSetProperty *ins);
 
     bool visitCheckOverRecursed(LCheckOverRecursed *lir);
     bool visitCheckOverRecursedFailure(CheckOverRecursedFailure *ool);
 
     bool visitUnboxDouble(LUnboxDouble *lir);
     bool visitOutOfLineUnboxDouble(OutOfLineUnboxDouble *ool);
     bool visitOutOfLineCacheGetProperty(OutOfLineCache *ool);
     bool visitOutOfLineCacheSetProperty(OutOfLineCache *ool);
@@ -149,23 +150,16 @@ class CodeGenerator : public CodeGenerat
     }
     bool visitCacheSetPropertyV(LCacheSetPropertyV *ins) {
         return visitCache(ins);
     }
     bool visitCacheSetPropertyT(LCacheSetPropertyT *ins) {
         return visitCache(ins);
     }
 
-    bool visitCallSetPropertyV(LCallSetPropertyV *ins) {
-        return visitCallSetProperty(ins);
-    }
-    bool visitCallSetPropertyT(LCallSetPropertyT *ins) {
-        return visitCallSetProperty(ins);
-    }
-
   private:
     bool visitCache(LInstruction *load);
     bool visitCallSetProperty(LInstruction *ins);
 
     ConstantOrRegister getSetPropertyValue(LInstruction *ins);
 };
 
 } // namespace ion
--- a/js/src/ion/IonBuilder.cpp
+++ b/js/src/ion/IonBuilder.cpp
@@ -3471,19 +3471,23 @@ IonBuilder::jsop_setprop(JSAtom *atom)
             MStoreFixedSlot *fixed = MStoreFixedSlot::New(obj, value, slot);
             current->add(fixed);
             current->push(value);
             return resumeAfter(fixed);
         }
     }
 
     oracle->binaryOp(script, pc);
-    MGenericSetProperty *ins = MGenericSetProperty::New(obj, value, atom,
-                                                        script->strictModeCode,
-                                                        monitored);
+
+    MSetPropertyInstruction *ins;
+    if (monitored)
+        ins = MCallSetProperty::New(obj, value, atom, script->strictModeCode);
+    else
+        ins = MSetPropertyCache::New(obj, value, atom, script->strictModeCode);
+
     current->add(ins);
     current->push(value);
 
     return resumeAfter(ins);
 }
 
 bool
 IonBuilder::jsop_regexp(RegExpObject *reobj)
--- a/js/src/ion/LIR-Common.h
+++ b/js/src/ion/LIR-Common.h
@@ -1645,70 +1645,47 @@ class LCallSetElement : public LCallInst
     LIR_HEADER(CallSetElement);
     BOX_OUTPUT_ACCESSORS();
 
     static const size_t Index = 1;
     static const size_t Value = 1 + BOX_PIECES;
 };
 
 // Call a stub to perform a property or name assignment of a generic value.
-class LCallSetPropertyV : public LCallInstructionHelper<0, 1 + BOX_PIECES, 0>
+class LCallSetProperty : public LCallInstructionHelper<0, 1 + BOX_PIECES, 0>
 {
   public:
-    LIR_HEADER(CallSetPropertyV);
+    LIR_HEADER(CallSetProperty);
 
-    LCallSetPropertyV(const LAllocation &obj) {
+    LCallSetProperty(const LAllocation &obj) {
         setOperand(0, obj);
     }
 
     static const size_t Value = 1;
 
-    const MGenericSetProperty *mir() const {
-        return mir_->toGenericSetProperty();
-    }
-};
-
-// Call a stub to perform a property or name assignment of a typed value.
-class LCallSetPropertyT : public LCallInstructionHelper<0, 2, 0>
-{
-    MIRType valueType_;
-
-  public:
-    LIR_HEADER(CallSetPropertyT);
-
-    LCallSetPropertyT(const LAllocation &obj, const LAllocation &value, MIRType valueType)
-        : valueType_(valueType)
-    {
-        setOperand(0, obj);
-        setOperand(1, value);
-    }
-
-    const MGenericSetProperty *mir() const {
-        return mir_->toGenericSetProperty();
-    }
-    MIRType valueType() {
-        return valueType_;
+    const MCallSetProperty *mir() const {
+        return mir_->toCallSetProperty();
     }
 };
 
 // Patchable jump to stubs generated for a SetProperty cache, which stores a
 // boxed value.
 class LCacheSetPropertyV : public LInstructionHelper<0, 1 + BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(CacheSetPropertyV);
 
     LCacheSetPropertyV(const LAllocation &object) {
         setOperand(0, object);
     }
 
     static const size_t Value = 1;
 
-    const MGenericSetProperty *mir() const {
-        return mir_->toGenericSetProperty();
+    const MSetPropertyCache *mir() const {
+        return mir_->toSetPropertyCache();
     }
 };
 
 // Patchable jump to stubs generated for a SetProperty cache, which stores a
 // value of a known type.
 class LCacheSetPropertyT : public LInstructionHelper<0, 2, 0>
 {
     MIRType valueType_;
@@ -1718,18 +1695,18 @@ class LCacheSetPropertyT : public LInstr
 
     LCacheSetPropertyT(const LAllocation &object, const LAllocation &value, MIRType valueType)
         : valueType_(valueType)
     {
         setOperand(0, object);
         setOperand(1, value);
     }
 
-    const MGenericSetProperty *mir() const {
-        return mir_->toGenericSetProperty();
+    const MSetPropertyCache *mir() const {
+        return mir_->toSetPropertyCache();
     }
     MIRType valueType() {
         return valueType_;
     }
 };
 
 class LCallIteratorStart : public LCallInstructionHelper<1, 1, 0>
 {
--- a/js/src/ion/LOpcodes.h
+++ b/js/src/ion/LOpcodes.h
@@ -124,18 +124,17 @@
     _(FunctionEnvironment)          \
     _(GetPropertyCacheV)            \
     _(GetPropertyCacheT)            \
     _(CallGetProperty)              \
     _(CallGetName)                  \
     _(CallGetNameTypeOf)            \
     _(CallGetElement)               \
     _(CallSetElement)               \
-    _(CallSetPropertyV)             \
-    _(CallSetPropertyT)             \
+    _(CallSetProperty)              \
     _(CacheSetPropertyV)            \
     _(CacheSetPropertyT)            \
     _(CallIteratorStart)            \
     _(CallIteratorNext)             \
     _(CallIteratorMore)             \
     _(CallIteratorEnd)              \
     _(ArrayLength)                  \
     _(StringLength)                 \
--- a/js/src/ion/Lowering.cpp
+++ b/js/src/ion/Lowering.cpp
@@ -1127,44 +1127,48 @@ LIRGenerator::visitCallGetElement(MCallG
     if (!useBox(lir, LCallGetElement::RhsInput, ins->rhs()))
         return false;
     if (!defineVMReturn(lir, ins))
         return false;
     return assignSafepoint(lir, ins);
 }
 
 bool
-LIRGenerator::visitGenericSetProperty(MGenericSetProperty *ins)
+LIRGenerator::visitCallSetProperty(MCallSetProperty *ins)
+{
+    LInstruction *lir = new LCallSetProperty(useRegister(ins->obj()));
+    if (!useBox(lir, LCallSetProperty::Value, ins->value()))
+        return false;
+    if (!add(lir, ins))
+        return false;
+    return assignSafepoint(lir, ins);
+}
+
+bool
+LIRGenerator::visitSetPropertyCache(MSetPropertyCache *ins)
 {
     LUse obj = useRegister(ins->obj());
 
     LInstruction *lir;
     if (ins->value()->type() == MIRType_Value) {
-        if (ins->monitored())
-            lir = new LCallSetPropertyV(obj);
-        else
-            lir = new LCacheSetPropertyV(obj);
-        JS_STATIC_ASSERT(LCallSetPropertyV::Value == LCacheSetPropertyV::Value);
-        if (!useBox(lir, LCallSetPropertyV::Value, ins->value()))
+        lir = new LCacheSetPropertyV(obj);
+        if (!useBox(lir, LCacheSetPropertyV::Value, ins->value()))
             return false;
     } else {
         LAllocation value = useRegisterOrConstant(ins->value());
-        if (ins->monitored())
-            lir = new LCallSetPropertyT(obj, value, ins->value()->type());
-        else
-            lir = new LCacheSetPropertyT(obj, value, ins->value()->type());
+        lir = new LCacheSetPropertyT(obj, value, ins->value()->type());
     }
 
     if (!add(lir, ins))
         return false;
 
     return assignSafepoint(lir, ins);
 }
 
- bool
+bool
 LIRGenerator::visitCallSetElement(MCallSetElement *ins)
 {
     JS_ASSERT(ins->object()->type() == MIRType_Object);
     JS_ASSERT(ins->index()->type() == MIRType_Value);
     JS_ASSERT(ins->value()->type() == MIRType_Value);
 
     LCallSetElement *lir = new LCallSetElement();
     lir->setOperand(0, useRegister(ins->object()));
--- a/js/src/ion/Lowering.h
+++ b/js/src/ion/Lowering.h
@@ -165,17 +165,18 @@ class LIRGenerator : public LIRGenerator
     bool visitStoreFixedSlot(MStoreFixedSlot *ins);
     bool visitGetPropertyCache(MGetPropertyCache *ins);
     bool visitGuardClass(MGuardClass *ins);
     bool visitCallGetProperty(MCallGetProperty *ins);
     bool visitCallGetName(MCallGetName *ins);
     bool visitCallGetNameTypeOf(MCallGetNameTypeOf *ins);
     bool visitCallGetElement(MCallGetElement *ins);
     bool visitCallSetElement(MCallSetElement *ins);
-    bool visitGenericSetProperty(MGenericSetProperty *ins);
+    bool visitSetPropertyCache(MSetPropertyCache *ins);
+    bool visitCallSetProperty(MCallSetProperty *ins);
     bool visitIteratorStart(MIteratorStart *ins);
     bool visitIteratorNext(MIteratorNext *ins);
     bool visitIteratorMore(MIteratorMore *ins);
     bool visitIteratorEnd(MIteratorEnd *ins);
     bool visitStringLength(MStringLength *ins);
     bool visitThrow(MThrow *ins);
 
     bool visitGuardObject(MGuardObject *ins) {
--- a/js/src/ion/MIR.h
+++ b/js/src/ion/MIR.h
@@ -2920,53 +2920,82 @@ class MCallGetPropertyOrName
         // "x" can be set with defineProperty in "obj.x" which can have some
         // side-effect.  This instruction does a load, but it may also performs
         // store.
         return AliasSet::Load(AliasSet::Any) |
                AliasSet::Store(AliasSet::Any);
     }
 };
 
-class MGenericSetProperty
-  : public MBinaryInstruction,
-    public ObjectPolicy
+class MSetPropertyInstruction : public MBinaryInstruction
 {
     JSAtom *atom_;
     bool strict_;
-    bool monitored_;
-
-    MGenericSetProperty(MDefinition *obj, MDefinition *value, JSAtom *atom,
-                        bool strict, bool monitored)
+
+  protected:
+    MSetPropertyInstruction(MDefinition *obj, MDefinition *value, JSAtom *atom,
+                        bool strict)
       : MBinaryInstruction(obj, value),
-        atom_(atom), strict_(strict), monitored_(monitored)
+        atom_(atom), strict_(strict)
     {}
 
   public:
-    INSTRUCTION_HEADER(GenericSetProperty);
-
-    static MGenericSetProperty *New(MDefinition *obj, MDefinition *value, JSAtom *atom,
-                                    bool strict, bool monitored) {
-        return new MGenericSetProperty(obj, value, atom, strict, monitored);
-    }
-
     MDefinition *obj() const {
         return getOperand(0);
     }
     MDefinition *value() const {
         return getOperand(1);
     }
     JSAtom *atom() const {
         return atom_;
     }
     bool strict() const {
         return strict_;
     }
-    bool monitored() const {
-        return monitored_;
-    }
+};
+
+// Note: This uses CallSetElementPolicy to always box its second input,
+// ensuring we don't need two LIR instructions to lower this.
+class MCallSetProperty
+  : public MSetPropertyInstruction,
+    public CallSetElementPolicy
+{
+    MCallSetProperty(MDefinition *obj, MDefinition *value, JSAtom *atom, bool strict)
+      : MSetPropertyInstruction(obj, value, atom, strict)
+    {
+    }
+
+  public:
+    INSTRUCTION_HEADER(CallSetProperty);
+
+    static MCallSetProperty *New(MDefinition *obj, MDefinition *value, JSAtom *atom, bool strict) {
+        return new MCallSetProperty(obj, value, atom, strict);
+    }
+
+    TypePolicy *typePolicy() {
+        return this;
+    }
+};
+
+class MSetPropertyCache
+  : public MSetPropertyInstruction,
+    public ObjectPolicy
+{
+    MSetPropertyCache(MDefinition *obj, MDefinition *value, JSAtom *atom, bool strict)
+      : MSetPropertyInstruction(obj, value, atom, strict)
+    {
+    }
+
+  public:
+    INSTRUCTION_HEADER(SetPropertyCache);
+
+    static MSetPropertyCache *New(MDefinition *obj, MDefinition *value, JSAtom *atom, bool strict) {
+        return new MSetPropertyCache(obj, value, atom, strict);
+    }
+
     TypePolicy *typePolicy() {
         return this;
     }
 };
 
 class MCallGetProperty : public MCallGetPropertyOrName
 {
     MCallGetProperty(MDefinition *obj, JSAtom *atom)
--- a/js/src/ion/MOpcodes.h
+++ b/js/src/ion/MOpcodes.h
@@ -110,17 +110,18 @@ namespace ion {
     _(StoreElementHole)                                                     \
     _(LoadFixedSlot)                                                        \
     _(StoreFixedSlot)                                                       \
     _(CallGetProperty)                                                      \
     _(CallGetName)                                                          \
     _(CallGetNameTypeOf)                                                    \
     _(CallGetElement)                                                       \
     _(CallSetElement)                                                       \
-    _(GenericSetProperty)                                                   \
+    _(CallSetProperty)                                                      \
+    _(SetPropertyCache)                                                     \
     _(IteratorStart)                                                        \
     _(IteratorNext)                                                         \
     _(IteratorMore)                                                         \
     _(IteratorEnd)                                                          \
     _(StringLength)                                                         \
     _(Round)
 
 // Forward declarations of MIR types.