Bug 747289 - Part 2/2 - Update IonMonkey to use known DOM constants. r=sstangl
authorEric Faust <efaustbmo@gmail.com>
Wed, 28 Nov 2012 16:28:36 -0500
changeset 114409 c5c30b93ee5e109f9b3d7d55aafa1763c066f6c6
parent 114408 70c54d5c94b7b3914690c3a73dd0ab1a1a93b7d2
child 114410 a5f259c99090e7f87323d6326090e39e7560b2a5
push id23917
push useremorley@mozilla.com
push dateThu, 29 Nov 2012 14:20:29 +0000
treeherdermozilla-central@c72d38e7a212 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssstangl
bugs747289
milestone20.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
Bug 747289 - Part 2/2 - Update IonMonkey to use known DOM constants. r=sstangl
js/src/ion/IonBuilder.cpp
js/src/ion/IonBuilder.h
js/src/ion/MIR.h
--- a/js/src/ion/IonBuilder.cpp
+++ b/js/src/ion/IonBuilder.cpp
@@ -5346,17 +5346,18 @@ IonBuilder::jsop_not()
     current->add(ins);
     current->push(ins);
     return true;
 }
 
 
 inline bool
 IonBuilder::TestCommonPropFunc(JSContext *cx, types::StackTypeSet *types, HandleId id,
-                               JSFunction **funcp, bool isGetter, bool *isDOM)
+                               JSFunction **funcp, bool isGetter, bool *isDOM,
+                               MDefinition **guardOut)
 {
     JSObject *found = NULL;
     JSObject *foundProto = NULL;
 
     *funcp = NULL;
     *isDOM = false;
 
     bool thinkDOM = true;
@@ -5490,16 +5491,22 @@ IonBuilder::TestCommonPropFunc(JSContext
     // Add a shape guard on the prototype we found the property on. The rest of
     // the prototype chain is guarded by TI freezes. Note that a shape guard is
     // good enough here, even in the proxy case, because we have ensured there
     // are no lookup hooks for this property.
     MInstruction *wrapper = MConstant::New(ObjectValue(*foundProto));
     current->add(wrapper);
     wrapper = addShapeGuard(wrapper, foundProto->lastProperty(), Bailout_ShapeGuard);
 
+    // Pass the guard back so it can be an operand.
+    if (isGetter) {
+        JS_ASSERT(wrapper->isGuardShape());
+        *guardOut = wrapper;
+    }
+
     // Now we have to freeze all the property typesets to ensure there isn't a
     // lower shadowing getter or setter installed in the future.
     types::TypeObject *curType;
     for (unsigned i = 0; i < types->getObjectCount(); i++) {
         curType = types->getTypeObject(i);
         JSObject *obj = NULL;
         if (!curType) {
             obj = types->getSingleObject(i);
@@ -5952,32 +5959,36 @@ IonBuilder::getPropTryDefiniteSlot(bool 
 
 bool
 IonBuilder::getPropTryCommonGetter(bool *emitted, HandleId id, types::StackTypeSet *barrier,
                                    types::StackTypeSet *types, TypeOracle::UnaryTypes unaryTypes)
 {
     JS_ASSERT(*emitted == false);
     JSFunction *commonGetter;
     bool isDOM;
-
-    if (!TestCommonPropFunc(cx, unaryTypes.inTypes, id, &commonGetter, true, &isDOM))
+    MDefinition *guard;
+
+    if (!TestCommonPropFunc(cx, unaryTypes.inTypes, id, &commonGetter, true,
+                            &isDOM, &guard))
+    {
         return false;
+    }
     if (!commonGetter)
         return true;
 
     MDefinition *obj = current->pop();
     RootedFunction getter(cx, commonGetter);
 
     if (isDOM && TestShouldDOMCall(cx, unaryTypes.inTypes, getter)) {
         const JSJitInfo *jitinfo = getter->jitInfo();
-        MGetDOMProperty *get = MGetDOMProperty::New(jitinfo->op, obj, jitinfo->isInfallible);
+        MGetDOMProperty *get = MGetDOMProperty::New(jitinfo, obj, guard);
         current->add(get);
         current->push(get);
 
-        if (!resumeAfter(get))
+        if (get->isEffectful() && !resumeAfter(get))
             return false;
         if (!pushTypeBarrier(get, types, barrier))
             return false;
 
         *emitted = true;
         return true;
     }
 
@@ -6112,17 +6123,17 @@ IonBuilder::jsop_setprop(HandlePropertyN
         }
     }
 
     RootedId id(cx, NameToId(name));
     types::StackTypeSet *types = binaryTypes.lhsTypes;
 
     JSFunction *commonSetter;
     bool isDOM;
-    if (!TestCommonPropFunc(cx, types, id, &commonSetter, false, &isDOM))
+    if (!TestCommonPropFunc(cx, types, id, &commonSetter, false, &isDOM, NULL))
         return false;
     if (!monitored && commonSetter) {
         RootedFunction setter(cx, commonSetter);
         if (isDOM && TestShouldDOMCall(cx, types, setter)) {
             MSetDOMProperty *set = MSetDOMProperty::New(setter->jitInfo()->op, obj, value);
             if (!set)
                 return false;
 
--- a/js/src/ion/IonBuilder.h
+++ b/js/src/ion/IonBuilder.h
@@ -418,17 +418,18 @@ class IonBuilder : public MIRGenerator
     bool makeInliningDecision(AutoObjectVector &targets, uint32 argc);
 
     MCall *makeCallHelper(HandleFunction target, uint32 argc, bool constructing);
     bool makeCallBarrier(HandleFunction target, uint32 argc, bool constructing,
                          types::StackTypeSet *types, types::StackTypeSet *barrier);
 
     inline bool TestCommonPropFunc(JSContext *cx, types::StackTypeSet *types,
                                    HandleId id, JSFunction **funcp,
-                                   bool isGetter, bool *isDOM);
+                                   bool isGetter, bool *isDOM,
+                                   MDefinition **guardOut);
 
     bool annotateGetPropertyCache(JSContext *cx, MDefinition *obj, MGetPropertyCache *getPropCache,
                                   types::StackTypeSet *objTypes, types::StackTypeSet *pushedTypes);
 
     MGetPropertyCache *checkInlineableGetPropertyCache(uint32_t argc);
 
     MPolyInlineDispatch *
     makePolyInlineDispatch(JSContext *cx, AutoObjectVector &targets, int argc,
--- a/js/src/ion/MIR.h
+++ b/js/src/ion/MIR.h
@@ -4950,51 +4950,90 @@ class MSetDOMProperty
     }
 
     TypePolicy *typePolicy() {
         return this;
     }
 };
 
 class MGetDOMProperty
-  : public MAryInstruction<1>,
+  : public MAryInstruction<2>,
     public ObjectPolicy<0>
 {
-    const JSJitPropertyOp func_;
-    bool isInfallible_;
-
-    MGetDOMProperty(const JSJitPropertyOp func, MDefinition *obj, bool isInfallible)
-      : func_(func), isInfallible_(isInfallible)
+    const JSJitInfo *info_;
+
+    MGetDOMProperty(const JSJitInfo *jitinfo, MDefinition *obj, MDefinition *guard)
+      : info_(jitinfo)
     {
+        JS_ASSERT(jitinfo);
+
         initOperand(0, obj);
 
+        // Pin the guard as an operand if we want to hoist later
+        initOperand(1, guard);
+
+        // We are movable iff the jitinfo says we can be.
+        if (jitinfo->isConstant)
+            setMovable();
+
         setResultType(MIRType_Value);
     }
 
+  protected:
+    const JSJitInfo *info() const {
+        return info_;
+    }
+
   public:
     INSTRUCTION_HEADER(GetDOMProperty);
 
-    static MGetDOMProperty *New(const JSJitPropertyOp func, MDefinition *obj, bool isInfallible)
+    static MGetDOMProperty *New(const JSJitInfo *info, MDefinition *obj, MDefinition *guard)
     {
-        return new MGetDOMProperty(func, obj, isInfallible);
+        return new MGetDOMProperty(info, obj, guard);
     }
 
     const JSJitPropertyOp fun() {
-        return func_;
-    }
-    bool isInfallible() {
-        return isInfallible_;
+        return info_->op;
+    }
+    bool isInfallible() const {
+        return info_->isInfallible;
+    }
+    bool isDomConstant() const {
+        return info_->isConstant;
     }
     MDefinition *object() {
         return getOperand(0);
     }
 
     TypePolicy *typePolicy() {
         return this;
     }
+
+    bool congruentTo(MDefinition *const &ins) const {
+        if (!isDomConstant())
+            return false;
+
+        if (!ins->isGetDOMProperty())
+            return false;
+
+        // Checking the jitinfo is the same as checking the constant function
+        if (!(info() == ins->toGetDOMProperty()->info()))
+            return false;
+
+        return congruentIfOperandsEqual(ins);
+    }
+
+    AliasSet getAliasSet() const {
+        // The whole point of constancy is that it's non-effectful and doesn't
+        // conflict with anything
+        if (isDomConstant())
+            return AliasSet::None();
+        return AliasSet::Store(AliasSet::Any);
+    }
+
 };
 
 class MStringLength
   : public MUnaryInstruction,
     public StringPolicy
 {
     MStringLength(MDefinition *string)
       : MUnaryInstruction(string)