Bug 1145491 part 1. Only do the fast path for JSOP_BINDGNAME when the script doesn't have a polluted global. r=luke,jandem
☠☠ backed out by 3b7a4d9da546 ☠ ☠
authorBoris Zbarsky <bzbarsky@mit.edu>
Fri, 20 Mar 2015 21:34:18 -0400
changeset 263675 80344fd40d6bd9cc46d0941e5ca597bf31f142a0
parent 263674 17eec5f308895e69d8b701081654464bf0ff03e8
child 263676 cddba378a563030c6a0e76f8b034f1eb8c5c53a1
push id4718
push userraliiev@mozilla.com
push dateMon, 11 May 2015 18:39:53 +0000
treeherdermozilla-beta@c20c4ef55f08 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke, jandem
bugs1145491
milestone39.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 1145491 part 1. Only do the fast path for JSOP_BINDGNAME when the script doesn't have a polluted global. r=luke,jandem
js/src/frontend/BytecodeEmitter.cpp
js/src/jit/BaselineCompiler.cpp
js/src/jit/BaselineIC.cpp
js/src/jit/IonBuilder.cpp
js/src/vm/Interpreter.cpp
js/src/vm/Opcodes.h
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -6893,17 +6893,17 @@ EmitLexicalInitialization(ExclusiveConte
     if (!BindNameToSlot(cx, bce, pn))
         return false;
 
     jsatomid atomIndex;
     if (!MaybeEmitVarDecl(cx, bce, globalDefOp, pn, &atomIndex))
         return false;
 
     if (pn->getOp() != JSOP_INITLEXICAL) {
-        bool global = js_CodeSpec[pn->getOp()].format & JOF_GNAME;
+        bool global = IsGlobalOp(pn->getOp());
         if (!EmitIndex32(cx, global ? JSOP_BINDGNAME : JSOP_BINDNAME, atomIndex, bce))
             return false;
         if (Emit1(cx, bce, JSOP_SWAP) < 0)
             return false;
     }
 
     if (!pn->pn_cookie.isFree()) {
         if (!EmitVarOp(cx, pn, pn->getOp(), bce))
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -2083,18 +2083,22 @@ BaselineCompiler::emit_JSOP_GETGNAME()
     // Mark R0 as pushed stack value.
     frame.push(R0);
     return true;
 }
 
 bool
 BaselineCompiler::emit_JSOP_BINDGNAME()
 {
-    frame.push(ObjectValue(script->global()));
-    return true;
+    if (!script->hasPollutedGlobalScope()) {
+        frame.push(ObjectValue(script->global()));
+        return true;
+    }
+
+    return emit_JSOP_BINDNAME();
 }
 
 bool
 BaselineCompiler::emit_JSOP_SETPROP()
 {
     // Keep lhs in R0, rhs in R1.
     frame.popRegsAndSync(2);
 
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -6197,17 +6197,17 @@ ICGetName_Scope<NumHops>::Compiler::gene
 static bool
 DoBindNameFallback(JSContext *cx, BaselineFrame *frame, ICBindName_Fallback *stub,
                    HandleObject scopeChain, MutableHandleValue res)
 {
     jsbytecode *pc = stub->icEntry()->pc(frame->script());
     mozilla::DebugOnly<JSOp> op = JSOp(*pc);
     FallbackICSpew(cx, stub, "BindName(%s)", js_CodeName[JSOp(*pc)]);
 
-    MOZ_ASSERT(op == JSOP_BINDNAME);
+    MOZ_ASSERT(op == JSOP_BINDNAME || op == JSOP_BINDGNAME);
 
     RootedPropertyName name(cx, frame->script()->getName(pc));
 
     RootedObject scope(cx);
     if (!LookupNameUnqualified(cx, name, scopeChain, &scope))
         return false;
 
     res.setObject(*scope);
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -1816,19 +1816,16 @@ IonBuilder::inspectOpcode(JSOp op)
         return pushConstant(Int32Value(GET_UINT16(pc)));
 
       case JSOP_GETGNAME:
       {
         PropertyName *name = info().getAtom(pc)->asPropertyName();
         return jsop_getgname(name);
       }
 
-      case JSOP_BINDGNAME:
-        return pushConstant(ObjectValue(script()->global()));
-
       case JSOP_SETGNAME:
       case JSOP_STRICTSETGNAME:
       {
         PropertyName *name = info().getAtom(pc)->asPropertyName();
         JSObject *obj = &script()->global();
         return setStaticName(obj, name);
       }
 
@@ -1839,16 +1836,20 @@ IonBuilder::inspectOpcode(JSOp op)
       }
 
       case JSOP_GETINTRINSIC:
       {
         PropertyName *name = info().getAtom(pc)->asPropertyName();
         return jsop_intrinsic(name);
       }
 
+      case JSOP_BINDGNAME:
+        if (!script()->hasPollutedGlobalScope())
+            return pushConstant(ObjectValue(script()->global()));
+        // Fall through to JSOP_BINDNAME
       case JSOP_BINDNAME:
         return jsop_bindname(info().getName(pc));
 
       case JSOP_DUP:
         current->pushSlot(current->stackDepth() - 1);
         return true;
 
       case JSOP_DUP2:
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -2033,38 +2033,43 @@ CASE(JSOP_SETCONST)
     RootedObject &obj = rootObject0;
     obj = &REGS.fp()->varObj();
 
     if (!SetConstOperation(cx, obj, name, rval))
         goto error;
 }
 END_CASE(JSOP_SETCONST)
 
-CASE(JSOP_BINDGNAME)
-    PUSH_OBJECT(REGS.fp()->global());
-END_CASE(JSOP_BINDGNAME)
-
 CASE(JSOP_BINDINTRINSIC)
     PUSH_OBJECT(*cx->global()->intrinsicsHolder());
 END_CASE(JSOP_BINDINTRINSIC)
 
+CASE(JSOP_BINDGNAME)
 CASE(JSOP_BINDNAME)
 {
-    RootedObject &scopeChain = rootObject0;
-    scopeChain = REGS.fp()->scopeChain();
-
-    RootedPropertyName &name = rootName0;
-    name = script->getName(REGS.pc);
-
-    /* Assigning to an undeclared name adds a property to the global object. */
-    RootedObject &scope = rootObject1;
-    if (!LookupNameUnqualified(cx, name, scopeChain, &scope))
-        goto error;
-
-    PUSH_OBJECT(*scope);
+    JSOp op = JSOp(*REGS.pc);
+    if (op == JSOP_BINDNAME || script->hasPollutedGlobalScope()) {
+        RootedObject &scopeChain = rootObject0;
+        scopeChain = REGS.fp()->scopeChain();
+
+        RootedPropertyName &name = rootName0;
+        name = script->getName(REGS.pc);
+
+        /* Assigning to an undeclared name adds a property to the global object. */
+        RootedObject &scope = rootObject1;
+        if (!LookupNameUnqualified(cx, name, scopeChain, &scope))
+            goto error;
+
+        PUSH_OBJECT(*scope);
+    } else {
+        PUSH_OBJECT(REGS.fp()->global());
+    }
+
+    static_assert(JSOP_BINDNAME_LENGTH == JSOP_BINDGNAME_LENGTH,
+                  "We're sharing the END_CASE so the lengths better match");
 }
 END_CASE(JSOP_BINDNAME)
 
 #define BITWISE_OP(OP)                                                        \
     JS_BEGIN_MACRO                                                            \
         int32_t i, j;                                                         \
         if (!ToInt32(cx, REGS.stackHandleAt(-2), &i))                         \
             goto error;                                                       \
@@ -2716,16 +2721,18 @@ CASE(JSOP_GIMPLICITTHIS)
         RootedValue &v = rootValue0;
         if (!ComputeImplicitThis(cx, scope, &v))
             goto error;
         PUSH_COPY(v);
     } else {
         // Treat it like JSOP_UNDEFINED.
         PUSH_UNDEFINED();
     }
+    static_assert(JSOP_IMPLICITTHIS_LENGTH == JSOP_GIMPLICITTHIS_LENGTH,
+                  "We're sharing the END_CASE so the lengths better match");
 }
 END_CASE(JSOP_IMPLICITTHIS)
 
 CASE(JSOP_GETGNAME)
 CASE(JSOP_GETNAME)
 {
     RootedValue &rval = rootValue0;
 
--- a/js/src/vm/Opcodes.h
+++ b/js/src/vm/Opcodes.h
@@ -1764,19 +1764,20 @@ 1234567890123456789012345678901234567890
      */ \
     macro(JSOP_DEBUGAFTERYIELD,  208, "debugafteryield",  NULL,  1,  0,  0,  JOF_BYTE) \
     macro(JSOP_UNUSED209,     209, "unused209",    NULL,  1,  0,  0,  JOF_BYTE) \
     macro(JSOP_UNUSED210,     210, "unused210",    NULL,  1,  0,  0,  JOF_BYTE) \
     macro(JSOP_UNUSED211,     211, "unused211",    NULL,  1,  0,  0,  JOF_BYTE) \
     macro(JSOP_UNUSED212,     212, "unused212",    NULL,  1,  0,  0,  JOF_BYTE) \
     macro(JSOP_UNUSED213,     213, "unused213",    NULL,  1,  0,  0,  JOF_BYTE) \
     /*
-     * Pushes the global scope onto the stack.
+     * Pushes the global scope onto the stack if the script doesn't have a
+     * polluted global scope.  Otherwise will act like JSOP_BINDNAME.
      *
-     * 'nameIndex' is not used.
+     * 'nameIndex' is only used when acting like JSOP_BINDNAME.
      *   Category: Variables and Scopes
      *   Type: Free Variables
      *   Operands: uint32_t nameIndex
      *   Stack: => global
      */ \
     macro(JSOP_BINDGNAME,     214, "bindgname",    NULL,  5,  0,  1,  JOF_ATOM|JOF_NAME|JOF_SET|JOF_GNAME) \
     \
     /*