Bug 799818 part 3 - Guard for strings when inlining known constants. r=jandem
authorNicolas B. Pierron <nicolas.b.pierron@mozilla.com>
Fri, 19 Oct 2012 16:45:18 -0700
changeset 110834 9e4c7538d6a96b42da832fff0209aaaf16d7c6a7
parent 110833 e70b2e6a920777160858b9d105a89949af221a1f
child 110835 9af9ca79f02667fa7e4927f33283a3e1666ae366
push id23717
push userryanvm@gmail.com
push dateSat, 20 Oct 2012 16:43:11 +0000
treeherdermozilla-central@5d03feda2300 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs799818
milestone19.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 799818 part 3 - Guard for strings when inlining known constants. r=jandem
js/src/ion/IonBuilder.cpp
js/src/ion/Lowering.cpp
js/src/ion/Lowering.h
js/src/ion/MIR.h
js/src/ion/MOpcodes.h
--- a/js/src/ion/IonBuilder.cpp
+++ b/js/src/ion/IonBuilder.cpp
@@ -4413,24 +4413,26 @@ TestSingletonProperty(JSContext *cx, Han
 
     *isKnownConstant = true;
     return true;
 }
 
 static inline bool
 TestSingletonPropertyTypes(JSContext *cx, types::StackTypeSet *types,
                            HandleObject globalObj, HandleId id,
-                           bool *isKnownConstant, bool *testObject)
+                           bool *isKnownConstant, bool *testObject,
+                           bool *testString)
 {
     // As for TestSingletonProperty, but the input is any value in a type set
     // rather than a specific object. If testObject is set then the constant
     // result can only be used after ensuring the input is an object.
 
     *isKnownConstant = false;
     *testObject = false;
+    *testString = false;
 
     if (!types || types->unknownObject())
         return true;
 
     RootedObject singleton(cx, types->getSingleton());
     if (singleton)
         return TestSingletonProperty(cx, singleton, id, isKnownConstant);
 
@@ -4450,16 +4452,25 @@ TestSingletonPropertyTypes(JSContext *cx
         break;
 
       case JSVAL_TYPE_BOOLEAN:
         key = JSProto_Boolean;
         break;
 
       case JSVAL_TYPE_OBJECT:
       case JSVAL_TYPE_UNKNOWN: {
+        if (types->hasType(types::Type::StringType())) {
+            // Do not optimize if the object is either a String or an Object.
+            if (types->maybeObject())
+                return true;
+            key = JSProto_String;
+            *testString = true;
+            break;
+        }
+
         // For property accesses which may be on many objects, we just need to
         // find a prototype common to all the objects; if that prototype
         // has the singleton property, the access will not be on a missing property.
         bool thoughtConstant = true;
         for (unsigned i = 0; i < types->getObjectCount(); i++) {
             types::TypeObject *object = types->getTypeObject(i);
             if (!object) {
                 // Try to get it through the singleton.
@@ -5879,28 +5890,32 @@ IonBuilder::getPropTryConstant(bool *emi
 {
     JS_ASSERT(*emitted == false);
     JSObject *singleton = types ? types->getSingleton() : NULL;
     if (!singleton || barrier)
         return true;
 
     RootedObject global(cx, &script_->global());
 
-    bool isConstant, testObject;
-    if (!TestSingletonPropertyTypes(cx, unaryTypes.inTypes, global, id, &isConstant, &testObject))
+    bool isConstant, testObject, testString;
+    if (!TestSingletonPropertyTypes(cx, unaryTypes.inTypes, global, id,
+                                    &isConstant, &testObject, &testString))
         return false;
 
     if (!isConstant)
         return true;
 
     MDefinition *obj = current->pop();
 
     // Property access is a known constant -- safe to emit.
+	JS_ASSERT(!testString || !testObject);
     if (testObject)
         current->add(MGuardObject::New(obj));
+	else if (testString)
+        current->add(MGuardString::New(obj));
 
     MConstant *known = MConstant::New(ObjectValue(*singleton));
     if (singleton->isFunction()) {
         RootedFunction singletonFunc(cx, singleton->toFunction());
         if (TestAreKnownDOMTypes(cx, unaryTypes.inTypes) &&
             TestShouldDOMCall(cx, unaryTypes.inTypes, singletonFunc))
         {
             FreezeDOMTypes(cx, unaryTypes.inTypes);
--- a/js/src/ion/Lowering.cpp
+++ b/js/src/ion/Lowering.cpp
@@ -1714,16 +1714,25 @@ LIRGenerator::visitGuardObject(MGuardObj
 {
     // The type policy does all the work, so at this point the input
     // is guaranteed to be an object.
     JS_ASSERT(ins->input()->type() == MIRType_Object);
     return redefine(ins, ins->input());
 }
 
 bool
+LIRGenerator::visitGuardString(MGuardString *ins)
+{
+    // The type policy does all the work, so at this point the input
+    // is guaranteed to be a string.
+    JS_ASSERT(ins->input()->type() == MIRType_String);
+    return redefine(ins, ins->input());
+}
+
+bool
 LIRGenerator::visitCallGetProperty(MCallGetProperty *ins)
 {
     LCallGetProperty *lir = new LCallGetProperty();
     if (!useBoxAtStart(lir, LCallGetProperty::Value, ins->value()))
         return false;
     return defineVMReturn(lir, ins) && assignSafepoint(lir, ins);
 }
 
--- a/js/src/ion/Lowering.h
+++ b/js/src/ion/Lowering.h
@@ -160,16 +160,17 @@ class LIRGenerator : public LIRGenerator
     bool visitClampToUint8(MClampToUint8 *ins);
     bool visitLoadFixedSlot(MLoadFixedSlot *ins);
     bool visitStoreFixedSlot(MStoreFixedSlot *ins);
     bool visitGetPropertyCache(MGetPropertyCache *ins);
     bool visitGetElementCache(MGetElementCache *ins);
     bool visitBindNameCache(MBindNameCache *ins);
     bool visitGuardClass(MGuardClass *ins);
     bool visitGuardObject(MGuardObject *ins);
+    bool visitGuardString(MGuardString *ins);
     bool visitCallGetProperty(MCallGetProperty *ins);
     bool visitDeleteProperty(MDeleteProperty *ins);
     bool visitGetNameCache(MGetNameCache *ins);
     bool visitCallGetElement(MCallGetElement *ins);
     bool visitCallSetElement(MCallSetElement *ins);
     bool visitSetPropertyCache(MSetPropertyCache *ins);
     bool visitCallSetProperty(MCallSetProperty *ins);
     bool visitIteratorStart(MIteratorStart *ins);
--- a/js/src/ion/MIR.h
+++ b/js/src/ion/MIR.h
@@ -1496,16 +1496,47 @@ class MGuardObject : public MUnaryInstru
     TypePolicy *typePolicy() {
         return this;
     }
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
 };
 
+class MGuardString
+  : public MUnaryInstruction,
+    public StringPolicy
+{
+    MGuardString(MDefinition *ins)
+      : MUnaryInstruction(ins)
+    {
+        setGuard();
+        setMovable();
+        setResultType(MIRType_String);
+    }
+
+  public:
+    INSTRUCTION_HEADER(GuardString);
+
+    static MGuardString *New(MDefinition *ins) {
+        return new MGuardString(ins);
+    }
+
+    MDefinition *input() const {
+        return getOperand(0);
+    }
+
+    TypePolicy *typePolicy() {
+        return this;
+    }
+    AliasSet getAliasSet() const {
+        return AliasSet::None();
+    }
+};
+
 // Caller-side allocation of |this| for |new|:
 // Given a prototype operand, construct |this| for JSOP_NEW.
 // For native constructors, returns MagicValue(JS_IS_CONSTRUCTING).
 class MCreateThis
   : public MAryInstruction<2>,
     public MixPolicy<ObjectPolicy<0>, ObjectPolicy<1> >
 {
     // Template for |this|, provided by TI, or NULL.
--- a/js/src/ion/MOpcodes.h
+++ b/js/src/ion/MOpcodes.h
@@ -58,16 +58,17 @@ namespace ion {
     _(Concat)                                                               \
     _(CharCodeAt)                                                           \
     _(FromCharCode)                                                         \
     _(Return)                                                               \
     _(Throw)                                                                \
     _(Box)                                                                  \
     _(Unbox)                                                                \
     _(GuardObject)                                                          \
+    _(GuardString)                                                          \
     _(ToDouble)                                                             \
     _(ToInt32)                                                              \
     _(TruncateToInt32)                                                      \
     _(ToString)                                                             \
     _(NewSlots)                                                             \
     _(NewArray)                                                             \
     _(NewObject)                                                            \
     _(NewCallObject)                                                        \