Backout 73f735acc3e1.
authorSean Stangl <sstangl@mozilla.com>
Tue, 16 Oct 2012 13:17:59 -0700
changeset 110599 55d64487e54a85cd634aa2a226b56b8c611e1ab4
parent 110598 5545892376ccdf9ed234accb60fcfc2d83a6b330
child 110600 69e943a96a429913bc4a11322cb21456cdef83e2
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
milestone19.0a1
backs out73f735acc3e1ee32b5f2e5c3017cbd8defb0d51c
Backout 73f735acc3e1.
js/src/ion/IonBuilder.cpp
js/src/ion/IonBuilder.h
--- a/js/src/ion/IonBuilder.cpp
+++ b/js/src/ion/IonBuilder.cpp
@@ -5800,289 +5800,191 @@ IonBuilder::storeSlot(MDefinition *obj, 
     if (needsBarrier)
         store->setNeedsBarrier();
     return resumeAfter(store);
 }
 
 bool
 IonBuilder::jsop_getprop(HandlePropertyName name)
 {
-    RootedId id(cx, NameToId(name));
+    LazyArgumentsType isArguments = oracle->propertyReadMagicArguments(script_, pc);
+    if (isArguments == MaybeArguments)
+        return abort("Type is not definitely lazy arguments.");
+    if (isArguments == DefinitelyArguments) {
+        if (JSOp(*pc) == JSOP_LENGTH)
+            return jsop_arguments_length();
+        // Can also be a callee.
+    }
+
     MDefinition *obj = current->pop();
+    MInstruction *ins;
 
     types::StackTypeSet *barrier = oracle->propertyReadBarrier(script_, pc);
     types::StackTypeSet *types = oracle->propertyRead(script_, pc);
+
     TypeOracle::Unary unary = oracle->unaryOp(script_, pc);
-    TypeOracle::UnaryTypes uTypes = oracle->unaryTypes(script_, pc);
-
-    bool emitted = false;
-
-    // Try to optimize arguments.length.
-    if (!getPropTryArgumentsLength(&emitted) || emitted)
-        return emitted;
-
-    // Try to hardcode known constants.
-    if (!getPropTryConstant(&emitted, obj, id, barrier, types, uTypes) || emitted)
-        return emitted;
-
-    // Try to emit loads from definite slots.
-    if (!getPropTryDefiniteSlot(&emitted, obj, name, barrier, types, unary, uTypes) || emitted)
-        return emitted;
-
-    // Try to inline a common property getter, or make a call.
-    if (!getPropTryCommonGetter(&emitted, obj, id, barrier, types, uTypes) || emitted)
-        return emitted;
-
-    // Try to emit a monomorphic cache based on data in JM caches.
-    if (!getPropTryMonomorphic(&emitted, obj, id, barrier, unary, uTypes) || emitted)
-        return emitted;
-
-    // Try to emit a polymorphic cache.
-    if (!getPropTryPolymorphic(&emitted, obj, name, id, barrier, types, unary, uTypes) || emitted)
-        return emitted;
-
-    // Emit a call.
-    MCallGetProperty *call = MCallGetProperty::New(obj, name);
-    current->add(call);
-    current->push(call);
-    if (!resumeAfter(call))
-        return false;
-
-    monitorResult(call, barrier, types);
-    return pushTypeBarrier(call, types, barrier);
-}
-
-bool
-IonBuilder::getPropTryArgumentsLength(bool *emitted)
-{
-    JS_ASSERT(*emitted == false);
-    LazyArgumentsType isArguments = oracle->propertyReadMagicArguments(script_, pc);
-
-    if (isArguments == MaybeArguments)
-        return abort("Type is not definitely lazy arguments.");
-    if (isArguments != DefinitelyArguments)
-        return true;
-    if (JSOp(*pc) != JSOP_LENGTH)
-        return true;
-
-    *emitted = true;
-    return jsop_arguments_length();
-}
-
-bool
-IonBuilder::getPropTryConstant(bool *emitted, MDefinition *obj, HandleId id,
-                               types::StackTypeSet *barrier, types::StackTypeSet *types,
-                               TypeOracle::UnaryTypes unaryTypes)
-{
-    JS_ASSERT(*emitted == false);
+    TypeOracle::UnaryTypes unaryTypes = oracle->unaryTypes(script_, pc);
+
+    RootedId id(cx, NameToId(name));
+
     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))
-        return false;
-
-    if (!isConstant)
-        return true;
-
-    // Property access is a known constant -- safe to emit.
-    if (testObject)
-        current->add(MGuardObject::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))
+    if (singleton && !barrier) {
+        bool isKnownConstant, testObject;
+        RootedObject global(cx, &script_->global());
+        if (!TestSingletonPropertyTypes(cx, unaryTypes.inTypes,
+                                        global, id,
+                                        &isKnownConstant, &testObject))
         {
-            FreezeDOMTypes(cx, unaryTypes.inTypes);
-            known->setDOMFunction();
+            return false;
+        }
+
+        if (isKnownConstant) {
+            if (testObject) {
+                MGuardObject *guard = MGuardObject::New(obj);
+                current->add(guard);
+            }
+            MConstant *known = MConstant::New(ObjectValue(*singleton));
+            current->add(known);
+            current->push(known);
+            if (singleton->isFunction()) {
+                RootedFunction singletonFunc(cx, singleton->toFunction());
+                if (TestAreKnownDOMTypes(cx, unaryTypes.inTypes) &&
+                    TestShouldDOMCall(cx, unaryTypes.inTypes, singletonFunc))
+                {
+                    FreezeDOMTypes(cx, unaryTypes.inTypes);
+                    known->setDOMFunction();
+                }
+            }
+            return true;
         }
     }
 
-    current->add(known);
-    current->push(known);
-
-    *emitted = true;
-    return true;
-}
-
-bool
-IonBuilder::getPropTryDefiniteSlot(bool *emitted, MDefinition *obj, HandlePropertyName name,
-                                   types::StackTypeSet *barrier, types::StackTypeSet *types,
-                                   TypeOracle::Unary unary, TypeOracle::UnaryTypes unaryTypes)
-{
-    JS_ASSERT(*emitted == false);
-    types::TypeSet *propTypes = GetDefiniteSlot(cx, unaryTypes.inTypes, name);
-    if (!propTypes)
-        return true;
-
-    MDefinition *useObj = obj;
-    if (unaryTypes.inTypes && unaryTypes.inTypes->baseFlags()) {
-        MGuardObject *guard = MGuardObject::New(obj);
-        current->add(guard);
-        useObj = guard;
+    if (types::TypeSet *propTypes = GetDefiniteSlot(cx, unaryTypes.inTypes, name)) {
+        MDefinition *useObj = obj;
+        if (unaryTypes.inTypes && unaryTypes.inTypes->baseFlags()) {
+            MGuardObject *guard = MGuardObject::New(obj);
+            current->add(guard);
+            useObj = guard;
+        }
+        MLoadFixedSlot *fixed = MLoadFixedSlot::New(useObj, propTypes->definiteSlot());
+        if (!barrier)
+            fixed->setResultType(unary.rval);
+
+        current->add(fixed);
+        current->push(fixed);
+
+        return pushTypeBarrier(fixed, types, barrier);
     }
 
-    MLoadFixedSlot *fixed = MLoadFixedSlot::New(useObj, propTypes->definiteSlot());
-    if (!barrier)
-        fixed->setResultType(unary.rval);
-
-    current->add(fixed);
-    current->push(fixed);
-
-    if (!pushTypeBarrier(fixed, types, barrier))
-        return false;
-
-    *emitted = true;
-    return true;
-}
-
-bool
-IonBuilder::getPropTryCommonGetter(bool *emitted, MDefinition *obj, HandleId id,
-                                   types::StackTypeSet *barrier, types::StackTypeSet *types,
-                                   TypeOracle::UnaryTypes unaryTypes)
-{
-    JS_ASSERT(*emitted == false);
+    // Attempt to inline common property getter. At least patch to call instead.
     JSFunction *commonGetter;
     bool isDOM;
-
     if (!TestCommonPropFunc(cx, unaryTypes.inTypes, id, &commonGetter, true, &isDOM))
-        return false;
-    if (!commonGetter)
-        return true;
-
-    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);
-        current->add(get);
-        current->push(get);
-
-        if (!resumeAfter(get))
-            return false;
-        if (!pushTypeBarrier(get, types, barrier))
-            return false;
-
-        *emitted = true;
-        return true;
+         return false;
+     if (commonGetter) {
+        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);
+
+            current->add(get);
+            current->push(get);
+
+            if (!resumeAfter(get))
+                return false;
+
+            return pushTypeBarrier(get, types, barrier);
+        }
+        // Spoof stack to expected state for call.
+        pushConstant(ObjectValue(*commonGetter));
+
+        MPassArg *wrapper = MPassArg::New(obj);
+        current->push(wrapper);
+        current->add(wrapper);
+
+        return makeCallBarrier(getter, 0, false, types, barrier);
     }
 
-    // Spoof stack to expected state for call.
-    pushConstant(ObjectValue(*commonGetter));
-
-    MPassArg *wrapper = MPassArg::New(obj);
-    current->add(wrapper);
-    current->push(wrapper);
-
-    if (!makeCallBarrier(getter, 0, false, types, barrier))
-        return false;
-
-    *emitted = true;
-    return true;
-}
-
-bool
-IonBuilder::getPropTryMonomorphic(bool *emitted, MDefinition *obj, HandleId id,
-                                  types::StackTypeSet *barrier, TypeOracle::Unary unary,
-                                  TypeOracle::UnaryTypes unaryTypes)
-{
-    JS_ASSERT(*emitted == false);
+    // If the input is guaranteed to be an object, then we want
+    // to specialize it via a slot load or an IC.
+
     bool accessGetter = oracle->propertyReadAccessGetter(script_, pc);
-
-    if (unary.ival != MIRType_Object)
-        return true;
-
-    Shape *objShape = mjit::GetPICSingleShape(cx, script_, pc, info().constructing());
-    if (!objShape || objShape->inDictionary()) {
-        spew("GETPROP not monomorphic");
-        return true;
-    }
-
-    // The JM IC was monomorphic, so we inline the property access as long as
-    // the shape is not in dictionary made. We cannot be sure that the shape is
-    // still a lastProperty, and calling Shape::search() on dictionary mode
-    // shapes that aren't lastProperty is invalid.
-    MGuardShape *guard = MGuardShape::New(obj, objShape, Bailout_CachedShapeGuard);
-    current->add(guard);
-
-    spew("Inlining monomorphic GETPROP");
-    Shape *shape = objShape->search(cx, id);
-    JS_ASSERT(shape);
-
     MIRType rvalType = unary.rval;
     if (barrier || IsNullOrUndefined(unary.rval) || accessGetter)
         rvalType = MIRType_Value;
 
-    if (!loadSlot(obj, shape, rvalType))
+    if (unary.ival == MIRType_Object) {
+        Shape *objShape;
+        if ((objShape = mjit::GetPICSingleShape(cx, script_, pc, info().constructing())) &&
+            !objShape->inDictionary())
+        {
+            // The JM IC was monomorphic, so we inline the property access as
+            // long as the shape is not in dictionary mode. We cannot be sure
+            // that the shape is still a lastProperty, and calling
+            // Shape::search() on dictionary mode shapes that aren't
+            // lastProperty is invalid.
+            MGuardShape *guard = MGuardShape::New(obj, objShape, Bailout_CachedShapeGuard);
+            current->add(guard);
+
+            spew("Inlining monomorphic GETPROP");
+
+            Shape *shape = objShape->search(cx, NameToId(name));
+            JS_ASSERT(shape);
+
+            return loadSlot(obj, shape, rvalType);
+        }
+
+        spew("GETPROP not monomorphic");
+
+        MGetPropertyCache *load = MGetPropertyCache::New(obj, name);
+        load->setResultType(rvalType);
+
+        // Try to mark the cache as idempotent. We only do this if JM is enabled
+        // (its ICs are used to mark property reads as likely non-idempotent) or
+        // if we are compiling eagerly (to improve test coverage).
+        if ((cx->methodJitEnabled || js_IonOptions.eagerCompilation) &&
+            !invalidatedIdempotentCache())
+        {
+            if (oracle->propertyReadIdempotent(script_, pc, id))
+                load->setIdempotent();
+        }
+
+        if (JSOp(*pc) == JSOP_CALLPROP) {
+            if (!annotateGetPropertyCache(cx, obj, load, unaryTypes.inTypes, types))
+                return false;
+        }
+
+        // If the cache is known to access getters, then enable generation of
+        // getter stubs and set its result type to value.
+        if (accessGetter)
+            load->setAllowGetters();
+
+        ins = load;
+    } else if (obj->type() == MIRType_Value && unaryTypes.inTypes->objectOrSentinel()) {
+        spew("GETPROP is object-or-sentinel");
+
+        MGetPropertyCache *load = MGetPropertyCache::New(obj, name);
+        load->setResultType(rvalType);
+        if (accessGetter)
+            load->setAllowGetters();
+
+        ins = load;
+    } else {
+        ins = MCallGetProperty::New(obj, name);
+    }
+
+    current->add(ins);
+    current->push(ins);
+
+    if (ins->isEffectful() && !resumeAfter(ins))
         return false;
 
-    *emitted = true;
-    return true;
-}
-
-bool
-IonBuilder::getPropTryPolymorphic(bool *emitted, MDefinition *obj,
-                                  HandlePropertyName name, HandleId id,
-                                  types::StackTypeSet *barrier, types::StackTypeSet *types,
-                                  TypeOracle::Unary unary, TypeOracle::UnaryTypes unaryTypes)
-{
-    JS_ASSERT(*emitted == false);
-    bool accessGetter = oracle->propertyReadAccessGetter(script_, pc);
-
-    // The input value must either be an object, or we should have strong suspicions
-    // that it can be safely unboxed to an object.
-    if (unary.ival != MIRType_Object && !unaryTypes.inTypes->objectOrSentinel())
-        return true;
-
-    MIRType rvalType = unary.rval;
-    if (barrier || IsNullOrUndefined(unary.rval) || accessGetter)
-        rvalType = MIRType_Value;
-
-    MGetPropertyCache *load = MGetPropertyCache::New(obj, name);
-    load->setResultType(rvalType);
-
-    // Try to mark the cache as idempotent. We only do this if JM is enabled
-    // (its ICs are used to mark property reads as likely non-idempotent) or
-    // if we are compiling eagerly (to improve test coverage).
-    if (unary.ival == MIRType_Object &&
-        (cx->methodJitEnabled || js_IonOptions.eagerCompilation) &&
-        !invalidatedIdempotentCache())
-    {
-        if (oracle->propertyReadIdempotent(script_, pc, id))
-            load->setIdempotent();
-    }
-
-    if (JSOp(*pc) == JSOP_CALLPROP) {
-        if (!annotateGetPropertyCache(cx, obj, load, unaryTypes.inTypes, types))
-            return false;
-    }
-
-    // If the cache is known to access getters, then enable generation of getter stubs.
-    if (accessGetter)
-        load->setAllowGetters();
-
-    current->add(load);
-    current->push(load);
-
-    if (load->isEffectful() && !resumeAfter(load))
-        return false;
-
-    if (accessGetter)
-        monitorResult(load, barrier, types);
-
-    if (!pushTypeBarrier(load, types, barrier))
-        return false;
-
-    *emitted = true;
-    return true;
+    if (ins->isCallGetProperty() || accessGetter)
+        monitorResult(ins, barrier, types);
+    return pushTypeBarrier(ins, types, barrier);
 }
 
 bool
 IonBuilder::jsop_setprop(HandlePropertyName name)
 {
     MDefinition *value = current->pop();
     MDefinition *obj = current->pop();
 
--- a/js/src/ion/IonBuilder.h
+++ b/js/src/ion/IonBuilder.h
@@ -283,35 +283,16 @@ class IonBuilder : public MIRGenerator
 
     JSObject *getNewArrayTemplateObject(uint32 count);
 
     bool invalidatedIdempotentCache();
 
     bool loadSlot(MDefinition *obj, Shape *shape, MIRType rvalType);
     bool storeSlot(MDefinition *obj, Shape *shape, MDefinition *value, bool needsBarrier);
 
-    // jsop_getprop() helpers.
-    bool getPropTryArgumentsLength(bool *emitted);
-    bool getPropTryConstant(bool *emitted, MDefinition *obj, HandleId id,
-                            types::StackTypeSet *barrier, types::StackTypeSet *types,
-                            TypeOracle::UnaryTypes unaryTypes);
-    bool getPropTryDefiniteSlot(bool *emitted, MDefinition *obj, HandlePropertyName name,
-                            types::StackTypeSet *barrier, types::StackTypeSet *types,
-                            TypeOracle::Unary unary, TypeOracle::UnaryTypes unaryTypes);
-    bool getPropTryCommonGetter(bool *emitted, MDefinition *obj, HandleId id,
-                            types::StackTypeSet *barrier, types::StackTypeSet *types,
-                            TypeOracle::UnaryTypes unaryTypes);
-    bool getPropTryMonomorphic(bool *emitted, MDefinition *obj, HandleId id,
-                            types::StackTypeSet *barrier, TypeOracle::Unary unary,
-                            TypeOracle::UnaryTypes unaryTypes);
-    bool getPropTryPolymorphic(bool *emitted, MDefinition *obj,
-                               HandlePropertyName name, HandleId id,
-                               types::StackTypeSet *barrier, types::StackTypeSet *types,
-                               TypeOracle::Unary unary, TypeOracle::UnaryTypes unaryTypes);
-
     bool jsop_add(MDefinition *left, MDefinition *right);
     bool jsop_bitnot();
     bool jsop_bitop(JSOp op);
     bool jsop_binary(JSOp op);
     bool jsop_binary(JSOp op, MDefinition *left, MDefinition *right);
     bool jsop_pos();
     bool jsop_neg();
     bool jsop_defvar(uint32 index);