Bug 1112162 part 2 - Add assertion & test case to verify that we keep the same alignment across the rectifier frame. r=bbouvier
authorNicolas B. Pierron <nicolas.b.pierron@mozilla.com>
Mon, 26 Jan 2015 12:07:58 +0100
changeset 225636 85f601fa7b46d37c5934870e79e882ca4e4ea2c8
parent 225635 e19c170e727f4e9d0786dd87c008da481c8d2a57
child 225637 42a50f81f29ddbf8740dc915fcd08dbc171cc4ab
push id54628
push usernpierron@mozilla.com
push dateMon, 26 Jan 2015 11:10:11 +0000
treeherdermozilla-inbound@85f601fa7b46 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbbouvier
bugs1112162
milestone38.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 1112162 part 2 - Add assertion & test case to verify that we keep the same alignment across the rectifier frame. r=bbouvier
js/src/builtin/TestingFunctions.cpp
js/src/jit-test/tests/ion/stack-alignment.js
js/src/jit/JitFrameIterator.h
js/src/jit/JitFrames.cpp
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -1348,21 +1348,21 @@ js::testingFunc_assertFloat32(JSContext 
     CallArgs args = CallArgsFromVp(argc, vp);
 
     // NOP when not in IonMonkey
     args.rval().setUndefined();
     return true;
 }
 
 static bool
-TestingFunc_assertValidJitStack(JSContext *cx, unsigned argc, jsval *vp)
+TestingFunc_assertJitStackInvariants(JSContext *cx, unsigned argc, jsval *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
-    jit::AssertValidJitStack(cx);
+    jit::AssertJitStackInvariants(cx);
     args.rval().setUndefined();
     return true;
 }
 
 static bool
 SetJitCompilerOption(JSContext *cx, unsigned argc, jsval *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
@@ -2494,18 +2494,18 @@ gc::ZealModeHelpText),
     JS_FN_HELP("getObjectMetadata", GetObjectMetadata, 1, 0,
 "getObjectMetadata(obj)",
 "  Get the metadata for an object."),
 
     JS_FN_HELP("bailout", testingFunc_bailout, 0, 0,
 "bailout()",
 "  Force a bailout out of ionmonkey (if running in ionmonkey)."),
 
-    JS_FN_HELP("assertValidJitStack", TestingFunc_assertValidJitStack, 0, 0,
-"assertValidJitStack()",
+    JS_FN_HELP("assertJitStackInvariants", TestingFunc_assertJitStackInvariants, 0, 0,
+"assertJitStackInvariants()",
 "  Iterates the Jit stack and check that stack invariants hold."),
 
     JS_FN_HELP("setJitCompilerOption", SetJitCompilerOption, 2, 0,
 "setCompilerOption(<option>, <number>)",
 "  Set a compiler option indexed in JSCompileOption enum to a number.\n"),
 
     JS_FN_HELP("setIonCheckGraphCoherency", SetIonCheckGraphCoherency, 1, 0,
 "setIonCheckGraphCoherency(bool)",
--- a/js/src/jit-test/tests/ion/stack-alignment.js
+++ b/js/src/jit-test/tests/ion/stack-alignment.js
@@ -1,14 +1,36 @@
 setJitCompilerOption("baseline.warmup.trigger", 10);
 setJitCompilerOption("ion.warmup.trigger", 30);
 var i;
 
 // Check that an entry frame is always aligned properly.
 function entryFrame_1() {
-  assertValidJitStack();
+  assertJitStackInvariants();
+}
+
+// Check rectifier frames are keeping the same alignment.
+function rectifierFrame_verify(a, b, c, d) {
+  assertJitStackInvariants();
+}
+
+function rectifierFrame_1(i) {
+  rectifierFrame_verify();
+}
+function rectifierFrame_2(i) {
+  rectifierFrame_verify(i);
+}
+function rectifierFrame_3(i) {
+  rectifierFrame_verify(i, i);
+}
+function rectifierFrame_4(i) {
+  rectifierFrame_verify(i, i, i);
 }
 
 for (i = 0; i < 40; i++) {
   entryFrame_1();
   entryFrame_1(0);
   entryFrame_1(0, 1);
+  rectifierFrame_1(i);
+  rectifierFrame_2(i);
+  rectifierFrame_3(i);
+  rectifierFrame_4(i);
 }
--- a/js/src/jit/JitFrameIterator.h
+++ b/js/src/jit/JitFrameIterator.h
@@ -84,18 +84,19 @@ class CommonFrameLayout;
 class JitFrameLayout;
 class ExitFrameLayout;
 
 class BaselineFrame;
 
 class JitActivation;
 
 // Iterate over the JIT stack to assert that all invariants are respected.
-//  - Check that all entry frames are aligned on StackAlignment.
-void AssertValidJitStack(JSContext *cx);
+//  - Check that all entry frames are aligned on JitStackAlignment.
+//  - Check that all rectifier frames keep the JitStackAlignment.
+void AssertJitStackInvariants(JSContext *cx);
 
 class JitFrameIterator
 {
   protected:
     uint8_t *current_;
     FrameType type_;
     uint8_t *returnAddressToFp_;
     size_t frameSize_;
--- a/js/src/jit/JitFrames.cpp
+++ b/js/src/jit/JitFrames.cpp
@@ -3021,22 +3021,40 @@ InvalidationBailoutStack::checkInvariant
     uint8_t *rawBase = ionScript()->method()->raw();
     uint8_t *rawLimit = rawBase + ionScript()->method()->instructionsSize();
     uint8_t *osiPoint = osiPointReturnAddress();
     MOZ_ASSERT(rawBase <= osiPoint && osiPoint <= rawLimit);
 #endif
 }
 
 void
-AssertValidJitStack(JSContext *cx)
+AssertJitStackInvariants(JSContext *cx)
 {
     for (JitActivationIterator activations(cx->runtime()); !activations.done(); ++activations) {
         JitFrameIterator frames(activations);
-        for (; !frames.done(); ++frames)
-            continue;
+        for (; !frames.done(); ++frames) {
+
+            if (frames.prevType() == JitFrame_Rectifier) {
+                size_t calleeFp = reinterpret_cast<size_t>(frames.fp());
+                size_t callerFp = reinterpret_cast<size_t>(frames.prevFp());
+                MOZ_ASSERT(callerFp >= calleeFp);
+                size_t frameSize = callerFp - calleeFp;
+
+                MOZ_RELEASE_ASSERT(frameSize % JitStackAlignment == 0,
+                  "The rectifier frame should keep the alignment");
+
+                size_t expectedFrameSize = 0
+                    + sizeof(Value) * (frames.callee()->nargs() + 1 /* |this| argument */ )
+                    + sizeof(JitFrameLayout);
+                MOZ_RELEASE_ASSERT(frameSize >= expectedFrameSize,
+                  "The frame is large enough to hold all arguments");
+                MOZ_RELEASE_ASSERT(expectedFrameSize + JitStackAlignment > frameSize,
+                  "The frame size is optimal");
+            }
+        }
 
         MOZ_RELEASE_ASSERT(frames.type() == JitFrame_Entry,
           "The first frame of a Jit activation should be an entry frame");
         MOZ_RELEASE_ASSERT(reinterpret_cast<size_t>(frames.fp()) % JitStackAlignment == 0,
           "The entry frame should be properly aligned");
     }
 }