Bug 875452 - Part 6: Refactor GetPropertyIC::canAttachNative() for unification with other get ICs. (r=shu)
authorEric Faust <efaustbmo@gmail.com>
Sat, 10 Aug 2013 22:20:36 -0700
changeset 142195 c81045074b71d32319d42f5591203e7a785d88a9
parent 142194 87a5139e77eb5a299e10e660b606d683c9f4594c
child 142196 7017a808158296b67d8fe462113d81b42681c8f0
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersshu
bugs875452
milestone26.0a1
Bug 875452 - Part 6: Refactor GetPropertyIC::canAttachNative() for unification with other get ICs. (r=shu)
js/src/jit/IonCaches.cpp
js/src/jit/IonCaches.h
--- a/js/src/jit/IonCaches.cpp
+++ b/js/src/jit/IonCaches.cpp
@@ -1073,81 +1073,92 @@ GenerateTypedArrayLength(JSContext *cx, 
     /* Success. */
     attacher.jumpRejoin(masm);
 
     /* Failure. */
     masm.bind(&failures);
     attacher.jumpNextStub(masm);
 }
 
-GetPropertyIC::NativeGetPropCacheability
-GetPropertyIC::canAttachNative(JSContext *cx, HandleObject obj, HandlePropertyName name,
-                               MutableHandleObject holder, MutableHandleShape shape)
+template <class GetPropCache>
+static GetPropertyIC::NativeGetPropCacheability
+CanAttachNativeGetProp(typename GetPropCache::Context cx, const GetPropCache &cache,
+                       HandleObject obj, HandlePropertyName name,
+                       MutableHandleObject holder, MutableHandleShape shape)
 {
     if (!obj || !obj->isNative())
-        return CanAttachNone;
-
-    // If the cache is idempotent, watch out for resolve hooks or non-native
-    // objects on the proto chain. We check this before calling lookupProperty,
-    // to make sure no effectful lookup hooks or resolve hooks are called.
-    if (idempotent() && !obj->hasIdempotentProtoChain())
-        return CanAttachNone;
-
-    if (!JSObject::lookupProperty(cx, obj, name, holder, shape))
-        return CanAttachError;
-
+        return GetPropertyIC::CanAttachNone;
+
+    // If the cache is idempotent or parallel, watch out for resolve hooks or
+    // non-native objects on the proto chain. We check this before calling
+    // lookupProperty, to make sure no effectful lookup hooks or resolve hooks
+    // are called.
+    if (cache.lookupNeedsIdempotentChain() && !obj->hasIdempotentProtoChain())
+        return GetPropertyIC::CanAttachNone;
+
+    if (!GetPropCache::doPropertyLookup(cx, obj, name, holder, shape))
+        return GetPropertyIC::CanAttachError;
+
+    RootedScript script(cx);
+    jsbytecode *pc;
+    cache.getScriptedLocation(&script, &pc);
     if (IsCacheableGetPropReadSlot(obj, holder, shape) ||
-        IsCacheableNoProperty(obj, holder, shape, pc, output()))
+        IsCacheableNoProperty(obj, holder, shape, pc, cache.output()))
     {
         // TI infers the possible types of native object properties. There's one
         // edge case though: for singleton objects it does not add the initial
-        // "undefined" type, see the propertySet comment in jsinfer.h. We can't
-        // monitor the return type inside an idempotent cache though, so we don't
-        // handle this case.
-        if (idempotent() &&
-            holder &&
-            holder->hasSingletonType() &&
-            holder->getSlot(shape->slot()).isUndefined())
-        {
-            return CanAttachNone;
-        }
-        return CanAttachReadSlot;
+        // "undefined" type, see the propertySet comment in jsinfer.h.
+        if (!cache.canMonitorSingletonUndefinedSlot(holder, shape))
+            return GetPropertyIC::CanAttachNone;
+        return GetPropertyIC::CanAttachReadSlot;
     }
 
     if (obj->is<ArrayObject>() && cx->names().length == name) {
         // The array length property is non-configurable, which means both that
         // checking the class of the object and the name of the property is enough
         // and that we don't need to worry about monitoring, since we know the
         // return type statically.
-        return CanAttachArrayLength;
+        return GetPropertyIC::CanAttachArrayLength;
     }
 
-    if (allowGetters() && (IsCacheableGetPropCallNative(obj, holder, shape) ||
-               IsCacheableGetPropCallPropertyOp(obj, holder, shape)))
+    if (cache.allowGetters() &&
+        (IsCacheableGetPropCallNative(obj, holder, shape) ||
+         IsCacheableGetPropCallPropertyOp(obj, holder, shape)))
     {
-        // Don't enable getter call if cache is idempotent, since
+        // Don't enable getter call if cache is parallel or idempotent, since
         // they can be effectful. This is handled by allowGetters()
-        return CanAttachCallGetter;
+        return GetPropertyIC::CanAttachCallGetter;
     }
 
-    // Return true only if one strategy is viable.
-    return CanAttachNone;
+    return GetPropertyIC::CanAttachNone;
+}
+
+bool
+GetPropertyIC::canMonitorSingletonUndefinedSlot(HandleObject holder, HandleShape shape) const
+{
+    // We can't monitor the return type inside an idempotent cache,
+    // so we don't handle this case.
+    return !(idempotent() &&
+             holder &&
+             holder->hasSingletonType() &&
+             holder->getSlot(shape->slot()).isUndefined());
 }
 
 bool
 GetPropertyIC::tryAttachNative(JSContext *cx, IonScript *ion, HandleObject obj,
                                HandlePropertyName name, void *returnAddr, bool *emitted)
 {
     JS_ASSERT(canAttachStub());
     JS_ASSERT(!*emitted);
 
     RootedShape shape(cx);
     RootedObject holder(cx);
 
-    NativeGetPropCacheability type = canAttachNative(cx, obj, name, &holder, &shape);
+    NativeGetPropCacheability type =
+        CanAttachNativeGetProp(cx, *this, obj, name, &holder, &shape);
     if (type == CanAttachError)
         return false;
     if (type == CanAttachNone)
         return true;
 
     *emitted = true;
 
     MacroAssembler masm(cx);
@@ -1347,18 +1358,18 @@ GetPropertyIC::tryAttachDOMProxyUnshadow
     JS_ASSERT(!*emitted);
     JS_ASSERT(IsCacheableDOMProxy(obj));
     JS_ASSERT(output().hasValue());
 
     RootedObject checkObj(cx, obj->getTaggedProto().toObjectOrNull());
     RootedObject holder(cx);
     RootedShape shape(cx);
 
-    NativeGetPropCacheability canCache = canAttachNative(cx, checkObj, name,
-                                                         &holder, &shape);
+    NativeGetPropCacheability canCache =
+        CanAttachNativeGetProp(cx, *this, checkObj, name, &holder, &shape);
 
     if (canCache == CanAttachError)
         return false;
     if (canCache == CanAttachNone)
         return true;
 
     *emitted = true;
 
--- a/js/src/jit/IonCaches.h
+++ b/js/src/jit/IonCaches.h
@@ -262,17 +262,17 @@ class IonCache
     }
 
     void setScriptedLocation(JSScript *script, jsbytecode *pc) {
         JS_ASSERT(!idempotent_);
         this->script = script;
         this->pc = pc;
     }
 
-    void getScriptedLocation(MutableHandleScript pscript, jsbytecode **ppc) {
+    void getScriptedLocation(MutableHandleScript pscript, jsbytecode **ppc) const {
         pscript.set(script);
         *ppc = pc;
     }
 };
 
 //
 // Repatch caches initially generate a patchable jump to an out of line call
 // to the cache function. Stubs are attached by appending: when attaching a
@@ -556,21 +556,26 @@ class GetPropertyIC : public RepatchIonC
     enum NativeGetPropCacheability {
         CanAttachError,
         CanAttachNone,
         CanAttachReadSlot,
         CanAttachArrayLength,
         CanAttachCallGetter
     };
 
-    /* Native Property Type helper */
-    NativeGetPropCacheability canAttachNative(JSContext *cx, HandleObject obj,
-                                              HandlePropertyName name,
-                                              MutableHandleObject holder,
-                                              MutableHandleShape shape);
+    // Helpers for CanAttachNativeGetProp
+    typedef JSContext * Context;
+    static bool doPropertyLookup(Context cx, HandleObject obj, HandlePropertyName name,
+                                 MutableHandleObject holder, MutableHandleShape shape) {
+        return JSObject::lookupProperty(cx, obj, name, holder, shape);
+    }
+    bool lookupNeedsIdempotentChain() const {
+        return idempotent();
+    }
+    bool canMonitorSingletonUndefinedSlot(HandleObject holder, HandleShape shape) const;
 
     // Attach the proper stub, if possible
     bool tryAttachStub(JSContext *cx, IonScript *ion, HandleObject obj,
                        HandlePropertyName name, void *returnAddr, bool *emitted);
     bool tryAttachProxy(JSContext *cx, IonScript *ion, HandleObject obj,
                         HandlePropertyName name, void *returnAddr, bool *emitted);
     bool tryAttachGenericProxy(JSContext *cx, IonScript *ion, HandleObject obj,
                                HandlePropertyName name, void *returnAddr, bool *emitted);