Bug 1145491 part 2. Only do the fast path for JSOP_GETGNAME when the script doesn't have a polluted global. r=luke,jandem
authorBoris Zbarsky <bzbarsky@mit.edu>
Fri, 20 Mar 2015 21:34:18 -0400
changeset 265383 1228e5205f122622a9e1597b89754c8e09491e1a
parent 265382 e1b68dc3654d7a314f785be3b99b234b46cb70ef
child 265384 0f9e79ad1715b4e6af11c252675bfdb2b7476517
push id830
push userraliiev@mozilla.com
push dateFri, 19 Jun 2015 19:24:37 +0000
treeherdermozilla-release@932614382a68 [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 2. Only do the fast path for JSOP_GETGNAME when the script doesn't have a polluted global. r=luke,jandem
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/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -2051,16 +2051,19 @@ BaselineCompiler::emit_JSOP_IN()
 
     frame.push(R0);
     return true;
 }
 
 bool
 BaselineCompiler::emit_JSOP_GETGNAME()
 {
+    if (script->hasPollutedGlobalScope())
+        return emit_JSOP_GETNAME();
+
     RootedPropertyName name(cx, script->getName(pc));
 
     if (name == cx->names().undefined) {
         frame.push(UndefinedValue());
         return true;
     }
     if (name == cx->names().NaN) {
         frame.push(cx->runtime()->NaNValue);
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -6056,16 +6056,18 @@ DoGetNameFallback(JSContext *cx, Baselin
     jsbytecode *pc = stub->icEntry()->pc(script);
     mozilla::DebugOnly<JSOp> op = JSOp(*pc);
     FallbackICSpew(cx, stub, "GetName(%s)", js_CodeName[JSOp(*pc)]);
 
     MOZ_ASSERT(op == JSOP_GETNAME || op == JSOP_GETGNAME);
 
     RootedPropertyName name(cx, script->getName(pc));
 
+    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 (!GetScopeNameForTypeOf(cx, scopeChain, name, res))
             return false;
     } else {
         if (!GetScopeName(cx, scopeChain, name, res))
             return false;
     }
 
@@ -6082,17 +6084,17 @@ DoGetNameFallback(JSContext *cx, Baselin
     // Attach new stub.
     if (stub->numOptimizedStubs() >= ICGetName_Fallback::MAX_OPTIMIZED_STUBS) {
         // TODO: Discard all stubs in this IC and replace with generic stub.
         return true;
     }
 
     bool attached = false;
     bool isTemporarilyUnoptimizable = false;
-    if (js_CodeSpec[*pc].format & JOF_GNAME) {
+    if (IsGlobalOp(JSOp(*pc)) && !script->hasPollutedGlobalScope()) {
         Handle<GlobalObject*> global = scopeChain.as<GlobalObject>();
         if (!TryAttachGlobalNameStub(cx, script, pc, stub, global, name, &attached,
                                      &isTemporarilyUnoptimizable))
         {
             return false;
         }
     } else {
         if (!TryAttachScopeNameStub(cx, script, stub, scopeChain, name, &attached))
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -1813,17 +1813,19 @@ IonBuilder::inspectOpcode(JSOp op)
         return pushConstant(Int32Value(GET_INT8(pc)));
 
       case JSOP_UINT16:
         return pushConstant(Int32Value(GET_UINT16(pc)));
 
       case JSOP_GETGNAME:
       {
         PropertyName *name = info().getAtom(pc)->asPropertyName();
-        return jsop_getgname(name);
+        if (!script()->hasPollutedGlobalScope())
+            return jsop_getgname(name);
+        return jsop_getname(name);
       }
 
       case JSOP_SETGNAME:
       case JSOP_STRICTSETGNAME:
       {
         PropertyName *name = info().getAtom(pc)->asPropertyName();
         JSObject *obj = &script()->global();
         return setStaticName(obj, name);
@@ -7566,17 +7568,17 @@ IonBuilder::jsop_getgname(PropertyName *
 
     return jsop_getname(name);
 }
 
 bool
 IonBuilder::jsop_getname(PropertyName *name)
 {
     MDefinition *object;
-    if (js_CodeSpec[*pc].format & JOF_GNAME) {
+    if (IsGlobalOp(JSOp(*pc)) && !script()->hasPollutedGlobalScope()) {
         MInstruction *global = constant(ObjectValue(script()->global()));
         object = global;
     } else {
         current->push(current->scopeChain());
         object = current->pop();
     }
 
     MGetNameCache *ins;
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -283,17 +283,17 @@ GetNameOperation(JSContext *cx, Interpre
      * Skip along the scope 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 scope chain
      * before the global object.
      */
-    if (IsGlobalOp(JSOp(*pc)))
+    if (IsGlobalOp(JSOp(*pc)) && !fp->script()->hasPollutedGlobalScope())
         obj = &obj->global();
 
     Shape *shape = nullptr;
     JSObject *scope = nullptr, *pobj = nullptr;
     if (LookupNameNoGC(cx, name, obj, &scope, &pobj, &shape)) {
         if (FetchNameNoGC(pobj, shape, vp))
             return CheckUninitializedLexical(cx, name, vp);
     }
@@ -2737,16 +2737,18 @@ CASE(JSOP_GETNAME)
 {
     RootedValue &rval = rootValue0;
 
     if (!GetNameOperation(cx, REGS.fp(), REGS.pc, &rval))
         goto error;
 
     PUSH_COPY(rval);
     TypeScript::Monitor(cx, script, REGS.pc, rval);
+    static_assert(JSOP_NAME_LEGNTH == JSOP_GETGNAME_LENGTH,
+                  "We're sharing the END_CASE so the lengths better match");
 }
 END_CASE(JSOP_GETNAME)
 
 CASE(JSOP_GETINTRINSIC)
 {
     RootedValue &rval = rootValue0;
 
     if (!GetIntrinsicOperation(cx, REGS.pc, &rval))
--- a/js/src/vm/Opcodes.h
+++ b/js/src/vm/Opcodes.h
@@ -1494,17 +1494,19 @@ 1234567890123456789012345678901234567890
      *   Category: Statements
      *   Type: Function
      *   Operands:
      *   Stack: =>
      */ \
     macro(JSOP_RETRVAL,       153,"retrval",    NULL,       1,  0,  0,  JOF_BYTE) \
     \
     /*
-     * Looks up name on global scope and pushes its value onto the stack.
+     * Looks up name on global scope and pushes its value onto the stack, unless
+     * the script has a polluted global, in which case it acts just like
+     * JSOP_NAME.
      *
      * Free variable references that must either be found on the global or a
      * ReferenceError.
      *   Category: Variables and Scopes
      *   Type: Free Variables
      *   Operands: uint32_t nameIndex
      *   Stack: => val
      */ \