Bug 1293575 - Skip update of frame arguments when the Arguments object aliases the formal arguments. r=jandem
authorNicolas B. Pierron <nicolas.b.pierron@gmail.com>
Mon, 30 Jul 2018 17:18:32 +0000
changeset 432408 5811b189a158716f420b8071c0841fd65b2cc71c
parent 432407 dca5444170e0a59c7a3a5321bece62d717fb6c1a
child 432409 56856b94af05f97c1ef66b0bbb71ce8be890a156
push id106729
push usernpierron@mozilla.com
push dateMon, 20 Aug 2018 16:24:32 +0000
treeherdermozilla-inbound@5811b189a158 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs1293575
milestone63.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 1293575 - Skip update of frame arguments when the Arguments object aliases the formal arguments. r=jandem
js/src/jit-test/tests/basic/bug1293575.js
js/src/jit/BaselineBailouts.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/bug1293575.js
@@ -0,0 +1,9 @@
+
+function f(y) {
+    y = 123456;
+    for (var x = 0; x < 9; ++x) {
+        z = arguments.callee.arguments;
+        assertEq(z[0], Math);
+    }
+}
+f(Math);
--- a/js/src/jit/BaselineBailouts.cpp
+++ b/js/src/jit/BaselineBailouts.cpp
@@ -791,34 +791,42 @@ InitFromBailout(JSContext* cx, size_t fr
 
         size_t thisvOffset = builder.framePushed() + JitFrameLayout::offsetOfThis();
         builder.valuePointerAtStackOffset(thisvOffset).set(thisv);
 
         MOZ_ASSERT(iter.numAllocations() >= CountArgSlots(script, fun));
         JitSpew(JitSpew_BaselineBailouts, "      frame slots %u, nargs %zu, nfixed %zu",
                 iter.numAllocations(), fun->nargs(), script->nfixed());
 
-        if (frameNo == 0) {
-            // This is the first frame. Store the formals in a Vector until we
-            // are done. Due to UCE and phi elimination, we could store an
-            // UndefinedValue() here for formals we think are unused, but
-            // locals may still reference the original argument slot
+        bool argsObjAliasesFormals = script->argsObjAliasesFormals();
+        if (frameNo == 0 && !argsObjAliasesFormals) {
+            // This is the first (outermost) frame and we don't have an
+            // arguments object aliasing the formals. Store the formals in a
+            // Vector until we are done. Due to UCE and phi elimination, we
+            // could store an UndefinedValue() here for formals we think are
+            // unused, but locals may still reference the original argument slot
             // (MParameter/LArgument) and expect the original Value.
             MOZ_ASSERT(startFrameFormals.empty());
             if (!startFrameFormals.resize(fun->nargs()))
                 return false;
         }
 
         for (uint32_t i = 0; i < fun->nargs(); i++) {
             Value arg = iter.read();
             JitSpew(JitSpew_BaselineBailouts, "      arg %d = %016" PRIx64,
                         (int) i, *((uint64_t*) &arg));
             if (frameNo > 0) {
                 size_t argOffset = builder.framePushed() + JitFrameLayout::offsetOfActualArg(i);
                 builder.valuePointerAtStackOffset(argOffset).set(arg);
+            } else if (argsObjAliasesFormals) {
+                // When the arguments object aliases the formal arguments, then
+                // JSOP_SETARG mutates the argument object. In such cases, the
+                // list of arguments reported by the snapshot are only aliases
+                // of argument object slots which are optimized to only store
+                // differences compared to arguments which are on the stack.
             } else {
                 startFrameFormals[i].set(arg);
             }
         }
     }
 
     for (uint32_t i = 0; i < script->nfixed(); i++) {
         Value slot = iter.read();