Bug 1144802 part 2. Add JIT and interpreter fast paths for JSOP_GIMPLICITTHIS when the script doesn't have a polluted scope. r=jandem
authorBoris Zbarsky <bzbarsky@mit.edu>
Fri, 20 Mar 2015 00:34:08 -0400
changeset 263535 228171a9cab881a65596e43a9959a2673cc01098
parent 263534 e8580bcdd658eef1fed6884cde5d27c0c3720186
child 263536 daa6b17cb3d455476b95bd2fd11ded2bbd1b9fa9
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)
reviewersjandem
bugs1144802
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 1144802 part 2. Add JIT and interpreter fast paths for JSOP_GIMPLICITTHIS when the script doesn't have a polluted scope. r=jandem
js/src/jit/BaselineCompiler.cpp
js/src/jit/IonBuilder.cpp
js/src/vm/Interpreter.cpp
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -1218,16 +1218,17 @@ BaselineCompiler::emit_JSOP_VOID()
     frame.pop();
     frame.push(UndefinedValue());
     return true;
 }
 
 bool
 BaselineCompiler::emit_JSOP_UNDEFINED()
 {
+    // If this ever changes, change what JSOP_GIMPLICITTHIS does too.
     frame.push(UndefinedValue());
     return true;
 }
 
 bool
 BaselineCompiler::emit_JSOP_HOLE()
 {
     frame.push(MagicValue(JS_ELEMENTS_HOLE));
@@ -2847,16 +2848,21 @@ BaselineCompiler::emit_JSOP_IMPLICITTHIS
 
     frame.push(R0);
     return true;
 }
 
 bool
 BaselineCompiler::emit_JSOP_GIMPLICITTHIS()
 {
+    if (!script->hasPollutedGlobalScope()) {
+        frame.push(UndefinedValue());
+        return true;
+    }
+
     return emit_JSOP_IMPLICITTHIS();
 }
 
 bool
 BaselineCompiler::emit_JSOP_INSTANCEOF()
 {
     frame.popRegsAndSync(2);
 
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -634,16 +634,20 @@ IonBuilder::analyzeNewLoopTypes(MBasicBl
             }
         } else {
             MIRType type = MIRType_None;
             switch (*last) {
               case JSOP_VOID:
               case JSOP_UNDEFINED:
                 type = MIRType_Undefined;
                 break;
+              case JSOP_GIMPLICITTHIS:
+                if (!script()->hasPollutedGlobalScope())
+                    type = MIRType_Undefined;
+                break;
               case JSOP_NULL:
                 type = MIRType_Null;
                 break;
               case JSOP_ZERO:
               case JSOP_ONE:
               case JSOP_INT8:
               case JSOP_INT32:
               case JSOP_UINT16:
@@ -1574,16 +1578,17 @@ IonBuilder::inspectOpcode(JSOp op)
       case JSOP_LINENO:
       case JSOP_LOOPENTRY:
         return true;
 
       case JSOP_LABEL:
         return jsop_label();
 
       case JSOP_UNDEFINED:
+        // If this ever changes, change what JSOP_GIMPLICITTHIS does too.
         return pushConstant(UndefinedValue());
 
       case JSOP_IFEQ:
         return jsop_ifeq(JSOP_IFEQ);
 
       case JSOP_TRY:
         return jsop_try();
 
@@ -1967,27 +1972,36 @@ IonBuilder::inspectOpcode(JSOp op)
         return jsop_instanceof();
 
       case JSOP_DEBUGLEAVEBLOCK:
         return true;
 
       case JSOP_DEBUGGER:
         return jsop_debugger();
 
+      case JSOP_GIMPLICITTHIS:
+        if (!script()->hasPollutedGlobalScope())
+            return pushConstant(UndefinedValue());
+
+        // Just fall through to the unsupported bytecode case.
+        break;
+
       default:
-        // Track a simpler message, since the actionable abort message is a
-        // static string, and the internal opcode name isn't an actionable
-        // thing anyways.
-        trackActionableAbort("Unsupported bytecode");
+        break;
+    }
+
+    // Track a simpler message, since the actionable abort message is a
+    // static string, and the internal opcode name isn't an actionable
+    // thing anyways.
+    trackActionableAbort("Unsupported bytecode");
 #ifdef DEBUG
-        return abort("Unsupported opcode: %s", js_CodeName[op]);
+    return abort("Unsupported opcode: %s", js_CodeName[op]);
 #else
-        return abort("Unsupported opcode: %d", op);
+    return abort("Unsupported opcode: %d", op);
 #endif
-    }
 }
 
 // Given that the current control flow structure has ended forcefully,
 // via a return, break, or continue (rather than joining), propagate the
 // termination up. For example, a return nested 5 loops deep may terminate
 // every outer loop at once, if there are no intervening conditionals:
 //
 // for (...) {
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -1763,16 +1763,17 @@ END_CASE(JSOP_LOOPENTRY)
 
 CASE(JSOP_LINENO)
 END_CASE(JSOP_LINENO)
 
 CASE(JSOP_FORCEINTERPRETER)
 END_CASE(JSOP_FORCEINTERPRETER)
 
 CASE(JSOP_UNDEFINED)
+    // If this ever changes, change what JSOP_GIMPLICITTHIS does too.
     PUSH_UNDEFINED();
 END_CASE(JSOP_UNDEFINED)
 
 CASE(JSOP_POP)
     REGS.sp--;
 END_CASE(JSOP_POP)
 
 CASE(JSOP_POPN)
@@ -2695,30 +2696,36 @@ CASE(JSOP_SETCALL)
     JS_ALWAYS_FALSE(SetCallOperation(cx));
     goto error;
 }
 END_CASE(JSOP_SETCALL)
 
 CASE(JSOP_IMPLICITTHIS)
 CASE(JSOP_GIMPLICITTHIS)
 {
-    RootedPropertyName &name = rootName0;
-    name = script->getName(REGS.pc);
-
-    RootedObject &scopeObj = rootObject0;
-    scopeObj = REGS.fp()->scopeChain();
-
-    RootedObject &scope = rootObject1;
-    if (!LookupNameWithGlobalDefault(cx, name, scopeObj, &scope))
-        goto error;
-
-    RootedValue &v = rootValue0;
-    if (!ComputeImplicitThis(cx, scope, &v))
-        goto error;
-    PUSH_COPY(v);
+    JSOp op = JSOp(*REGS.pc);
+    if (op == JSOP_IMPLICITTHIS || script->hasPollutedGlobalScope()) {
+        RootedPropertyName &name = rootName0;
+        name = script->getName(REGS.pc);
+
+        RootedObject &scopeObj = rootObject0;
+        scopeObj = REGS.fp()->scopeChain();
+
+        RootedObject &scope = rootObject1;
+        if (!LookupNameWithGlobalDefault(cx, name, scopeObj, &scope))
+            goto error;
+
+        RootedValue &v = rootValue0;
+        if (!ComputeImplicitThis(cx, scope, &v))
+            goto error;
+        PUSH_COPY(v);
+    } else {
+        // Treat it like JSOP_UNDEFINED.
+        PUSH_UNDEFINED();
+    }
 }
 END_CASE(JSOP_IMPLICITTHIS)
 
 CASE(JSOP_GETGNAME)
 CASE(JSOP_GETNAME)
 {
     RootedValue &rval = rootValue0;