Backed out changeset 82cdbd24d06f (bug 1341061) for failing crashtest 366271-1.html. r=backout
authorSebastian Hengst <archaeopteryx@coole-files.de>
Fri, 24 Feb 2017 23:10:56 +0100
changeset 489625 b5a2c80de72fc3b32c2ef44006e75c44917453d4
parent 489624 7b972ab5bd1a8cc31c7fe60ba0862cd8a845a709
child 489626 b623e256e1f4eb394f0f1d666e1c4a517e1f3e53
child 492053 4d4fda8dfac9cb81cbad108f13d03e1ab0960642
push id46871
push userbmo:sledru@mozilla.com
push dateSat, 25 Feb 2017 12:16:21 +0000
reviewersbackout
bugs1341061, 366271
milestone54.0a1
backs out82cdbd24d06fb79eea849d533137807bbbbd33b2
Backed out changeset 82cdbd24d06f (bug 1341061) for failing crashtest 366271-1.html. r=backout
js/src/jit/BaselineIC.cpp
js/src/jit/IonCaches.cpp
js/src/vm/Interpreter-inl.h
js/src/vm/Interpreter.cpp
js/src/vm/Interpreter.h
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -1278,20 +1278,20 @@ DoGetNameFallback(JSContext* cx, Baselin
                 attached = true;
             }
         }
     }
 
     static_assert(JSOP_GETGNAME_LENGTH == JSOP_GETNAME_LENGTH,
                   "Otherwise our check for JSOP_TYPEOF isn't ok");
     if (JSOp(pc[JSOP_GETGNAME_LENGTH]) == JSOP_TYPEOF) {
-        if (!GetEnvironmentName<GetNameMode::TypeOf>(cx, envChain, name, res))
+        if (!GetEnvironmentNameForTypeOf(cx, envChain, name, res))
             return false;
     } else {
-        if (!GetEnvironmentName<GetNameMode::Normal>(cx, envChain, name, res))
+        if (!GetEnvironmentName(cx, envChain, name, res))
             return false;
     }
 
     TypeScript::Monitor(cx, script, pc, res);
 
     // Check if debug mode toggling made the stub invalid.
     if (stub.invalid())
         return true;
--- a/js/src/jit/IonCaches.cpp
+++ b/js/src/jit/IonCaches.cpp
@@ -3383,20 +3383,20 @@ NameIC::update(JSContext* cx, HandleScri
     RootedObject obj(cx);
     RootedObject holder(cx);
     Rooted<PropertyResult> prop(cx);
     if (!LookupName(cx, name, envChain, &obj, &holder, &prop))
         return false;
 
     // Look first. Don't generate cache entries if the lookup fails.
     if (cache.isTypeOf()) {
-        if (!FetchName<GetNameMode::TypeOf>(cx, obj, holder, name, prop, vp))
+        if (!FetchName<true>(cx, obj, holder, name, prop, vp))
             return false;
     } else {
-        if (!FetchName<GetNameMode::Normal>(cx, obj, holder, name, prop, vp))
+        if (!FetchName<false>(cx, obj, holder, name, prop, vp))
             return false;
     }
 
     if (cache.canAttachStub()) {
         if (IsCacheableNameReadSlot(cx, envChain, obj, holder, prop, pc, cache.outputReg())) {
             if (!cache.attachReadSlot(cx, outerScript, ion, envChain, obj,
                                       holder.as<NativeObject>(), prop))
             {
--- a/js/src/vm/Interpreter-inl.h
+++ b/js/src/vm/Interpreter-inl.h
@@ -169,53 +169,44 @@ GetLengthProperty(const Value& lval, Mut
                 return true;
             }
         }
     }
 
     return false;
 }
 
-enum class GetNameMode
-{
-    Normal,
-    TypeOf
-};
-
-template <GetNameMode mode>
-inline bool
-FetchName(JSContext* cx, HandleObject receiver, HandleObject holder, HandlePropertyName name,
+template <bool TypeOf> inline bool
+FetchName(JSContext* cx, HandleObject obj, HandleObject obj2, HandlePropertyName name,
           Handle<PropertyResult> prop, MutableHandleValue vp)
 {
     if (!prop) {
-        switch (mode) {
-          case GetNameMode::Normal:
-            return ReportIsNotDefined(cx, name);
-          case GetNameMode::TypeOf:
+        if (TypeOf) {
             vp.setUndefined();
             return true;
         }
+        return ReportIsNotDefined(cx, name);
     }
 
     /* Take the slow path if shape was not found in a native object. */
-    if (!receiver->isNative() || !holder->isNative()) {
+    if (!obj->isNative() || !obj2->isNative()) {
         Rooted<jsid> id(cx, NameToId(name));
-        if (!GetProperty(cx, receiver, receiver, id, vp))
+        if (!GetProperty(cx, obj, obj, id, vp))
             return false;
     } else {
         RootedShape shape(cx, prop.shape());
-        RootedObject normalized(cx, receiver);
+        RootedObject normalized(cx, obj);
         if (normalized->is<WithEnvironmentObject>() && !shape->hasDefaultGetter())
             normalized = &normalized->as<WithEnvironmentObject>().object();
         if (shape->isDataDescriptor() && shape->hasDefaultGetter()) {
             /* Fast path for Object instance properties. */
             MOZ_ASSERT(shape->hasSlot());
-            vp.set(holder->as<NativeObject>().getSlot(shape->slot()));
+            vp.set(obj2->as<NativeObject>().getSlot(shape->slot()));
         } else {
-            if (!NativeGetExistingProperty(cx, normalized, holder.as<NativeObject>(), shape, vp))
+            if (!NativeGetExistingProperty(cx, normalized, obj2.as<NativeObject>(), shape, vp))
                 return false;
         }
     }
 
     // We do our own explicit checking for |this|
     if (name == cx->names().dotThis)
         return true;
 
@@ -233,39 +224,16 @@ FetchNameNoGC(JSObject* pobj, PropertyRe
     Shape* shape = prop.shape();
     if (!shape->isDataDescriptor() || !shape->hasDefaultGetter())
         return false;
 
     vp.set(pobj->as<NativeObject>().getSlot(shape->slot()));
     return !IsUninitializedLexical(vp);
 }
 
-template <js::GetNameMode mode>
-inline bool
-GetEnvironmentName(JSContext* cx, HandleObject envChain, HandlePropertyName name,
-                   MutableHandleValue vp)
-{
-    {
-        PropertyResult prop;
-        JSObject* obj = nullptr;
-        JSObject* pobj = nullptr;
-        if (LookupNameNoGC(cx, name, envChain, &obj, &pobj, &prop)) {
-            if (FetchNameNoGC(pobj, prop, vp))
-                return true;
-        }
-    }
-
-    Rooted<PropertyResult> prop(cx);
-    RootedObject obj(cx), pobj(cx);
-    if (!LookupName(cx, name, envChain, &obj, &pobj, &prop))
-        return false;
-
-    return FetchName<mode>(cx, obj, pobj, name, prop, vp);
-}
-
 inline bool
 GetIntrinsicOperation(JSContext* cx, jsbytecode* pc, MutableHandleValue vp)
 {
     RootedPropertyName name(cx, cx->currentScript()->getName(pc));
     return GlobalObject::getIntrinsicValue(cx, cx->global(), name, vp);
 }
 
 inline bool
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -190,49 +190,65 @@ GetPropertyOperation(JSContext* cx, Inte
     // Copy lval, because it might alias vp.
     RootedValue v(cx, lval);
     return GetProperty(cx, v, name, vp);
 }
 
 static inline bool
 GetNameOperation(JSContext* cx, InterpreterFrame* fp, jsbytecode* pc, MutableHandleValue vp)
 {
-    RootedObject envChain(cx, fp->environmentChain());
-    RootedPropertyName name(cx, fp->script()->getName(pc));
+    JSObject* obj = fp->environmentChain();
+    PropertyName* name = fp->script()->getName(pc);
 
     /*
      * Skip along the env chain to the enclosing global object. This is
      * used for GNAME opcodes where the bytecode emitter has determined a
      * name access must be on the global. It also insulates us from bugs
      * in the emitter: type inference will assume that GNAME opcodes are
      * accessing the global object, and the inferred behavior should match
      * the actual behavior even if the id could be found on the env chain
      * before the global object.
      */
     if (IsGlobalOp(JSOp(*pc)) && !fp->script()->hasNonSyntacticScope())
-        envChain = &envChain->global().lexicalEnvironment();
+        obj = &obj->global().lexicalEnvironment();
+
+    PropertyResult prop;
+    JSObject* env = nullptr;
+    JSObject* pobj = nullptr;
+    if (LookupNameNoGC(cx, name, obj, &env, &pobj, &prop)) {
+        if (FetchNameNoGC(pobj, prop, vp))
+            return true;
+    }
+
+    RootedObject objRoot(cx, obj), envRoot(cx), pobjRoot(cx);
+    RootedPropertyName nameRoot(cx, name);
+    Rooted<PropertyResult> propRoot(cx);
+
+    if (!LookupName(cx, nameRoot, objRoot, &envRoot, &pobjRoot, &propRoot))
+        return false;
 
     /* Kludge to allow (typeof foo == "undefined") tests. */
     JSOp op2 = JSOp(pc[JSOP_GETNAME_LENGTH]);
     if (op2 == JSOP_TYPEOF)
-        return GetEnvironmentName<GetNameMode::TypeOf>(cx, envChain, name, vp);
-    return GetEnvironmentName<GetNameMode::Normal>(cx, envChain, name, vp);
+        return FetchName<true>(cx, envRoot, pobjRoot, nameRoot, propRoot, vp);
+
+    return FetchName<false>(cx, envRoot, pobjRoot, nameRoot, propRoot, vp);
 }
 
 static inline bool
 GetImportOperation(JSContext* cx, InterpreterFrame* fp, jsbytecode* pc, MutableHandleValue vp)
 {
     RootedObject obj(cx, fp->environmentChain()), env(cx), pobj(cx);
     RootedPropertyName name(cx, fp->script()->getName(pc));
     Rooted<PropertyResult> prop(cx);
 
     MOZ_ALWAYS_TRUE(LookupName(cx, name, obj, &env, &pobj, &prop));
     MOZ_ASSERT(env && env->is<ModuleEnvironmentObject>());
     MOZ_ASSERT(env->as<ModuleEnvironmentObject>().hasImportBinding(name));
-    return FetchName<GetNameMode::Normal>(cx, env, pobj, name, prop, vp);
+    return FetchName<false>(cx, env, pobj, name, prop, vp);
 }
 
 static bool
 SetPropertyOperation(JSContext* cx, JSOp op, HandleValue lval, HandleId id, HandleValue rval)
 {
     MOZ_ASSERT(op == JSOP_SETPROP || op == JSOP_STRICTSETPROP);
 
     RootedObject obj(cx, ToObjectFromStack(cx, lval));
@@ -4293,16 +4309,64 @@ js::GetProperty(JSContext* cx, HandleVal
     RootedValue receiver(cx, v);
     RootedObject obj(cx, ToObjectFromStack(cx, v));
     if (!obj)
         return false;
 
     return GetProperty(cx, obj, receiver, name, vp);
 }
 
+bool
+js::GetEnvironmentName(JSContext* cx, HandleObject envChain, HandlePropertyName name,
+                       MutableHandleValue vp)
+{
+    Rooted<PropertyResult> prop(cx);
+    RootedObject obj(cx), pobj(cx);
+    if (!LookupName(cx, name, envChain, &obj, &pobj, &prop))
+        return false;
+
+    if (!prop)
+        return ReportIsNotDefined(cx, name);
+
+    if (!GetProperty(cx, obj, obj, name, vp))
+        return false;
+
+    // We do our own explicit checking for |this|
+    if (name == cx->names().dotThis)
+        return true;
+
+    // See note in FetchName.
+    return CheckUninitializedLexical(cx, name, vp);
+}
+
+/*
+ * Alternate form for NAME opcodes followed immediately by a TYPEOF,
+ * which do not report an exception on (typeof foo == "undefined") tests.
+ */
+bool
+js::GetEnvironmentNameForTypeOf(JSContext* cx, HandleObject envChain, HandlePropertyName name,
+                                MutableHandleValue vp)
+{
+    Rooted<PropertyResult> prop(cx);
+    RootedObject obj(cx), pobj(cx);
+    if (!LookupName(cx, name, envChain, &obj, &pobj, &prop))
+        return false;
+
+    if (!prop) {
+        vp.set(UndefinedValue());
+        return true;
+    }
+
+    if (!GetProperty(cx, obj, obj, name, vp))
+        return false;
+
+    // See note in FetchName.
+    return CheckUninitializedLexical(cx, name, vp);
+}
+
 JSObject*
 js::Lambda(JSContext* cx, HandleFunction fun, HandleObject parent)
 {
     MOZ_ASSERT(!fun->isArrow());
 
     RootedObject clone(cx, CloneFunctionObjectIfNotSingleton(cx, fun, parent));
     if (!clone)
         return nullptr;
--- a/js/src/vm/Interpreter.h
+++ b/js/src/vm/Interpreter.h
@@ -415,16 +415,24 @@ bool
 Throw(JSContext* cx, HandleValue v);
 
 bool
 ThrowingOperation(JSContext* cx, HandleValue v);
 
 bool
 GetProperty(JSContext* cx, HandleValue value, HandlePropertyName name, MutableHandleValue vp);
 
+bool
+GetEnvironmentName(JSContext* cx, HandleObject obj, HandlePropertyName name,
+                   MutableHandleValue vp);
+
+bool
+GetEnvironmentNameForTypeOf(JSContext* cx, HandleObject obj, HandlePropertyName name,
+                            MutableHandleValue vp);
+
 JSObject*
 Lambda(JSContext* cx, HandleFunction fun, HandleObject parent);
 
 JSObject*
 LambdaArrow(JSContext* cx, HandleFunction fun, HandleObject parent, HandleValue newTargetv);
 
 bool
 GetElement(JSContext* cx, MutableHandleValue lref, HandleValue rref, MutableHandleValue res);