[INFER] Mark functions uninlineable when calling Invoke on an already-inlined frame, bug 676491.
authorBrian Hackett <bhackett1024@gmail.com>
Fri, 05 Aug 2011 08:15:50 -0700
changeset 76099 4e4822ab5a03a68257863f8c34601ddd77bd3b0f
parent 76098 723b6c2995741f3c3c68aa83571834a8e7f8db20
child 76100 b849dfd77bcb9d9e67665cb37d8e351fc8564524
push id3
push userfelipc@gmail.com
push dateFri, 30 Sep 2011 20:09:13 +0000
bugs676491
milestone8.0a1
[INFER] Mark functions uninlineable when calling Invoke on an already-inlined frame, bug 676491.
js/src/jit-test/tests/jaeger/inline/bug676491.js
js/src/vm/Stack.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/jaeger/inline/bug676491.js
@@ -0,0 +1,14 @@
+Array.prototype.__defineSetter__(32, function() { print("Hello from arbitrary JS");});
+var UBound = 0;
+var expect= '';
+var expectedvalues = [];
+for (var j=0; j < 10; j++) {
+  addThis();
+  addThis();
+  addThis();
+  addThis();
+}
+function addThis() {
+  expectedvalues[UBound] = expect;
+  UBound++;
+}
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -576,31 +576,34 @@ ContextStack::ensureOnTop(JSContext *cx,
     /*
      * The only calls made by inlined methodjit frames can be to other JIT
      * frames associated with the same VMFrame. If we try to Invoke(),
      * Execute() or so forth, any topmost inline frame will need to be
      * expanded (along with other inline frames in the compartment).
      * To avoid pathological behavior here, make sure to mark any topmost
      * function as uninlineable, which will expand inline frames if there are
      * any and prevent the function from being inlined in the future.
+     *
+     * We can only do this if we are allowed to report errors --- otherwise the
+     * function's compartment may not be consistent with cx->compartment
+     * (cross-compartment call or SaveFrameChain). In such cases the caller
+     * must have already expanded inline frames.
      */
-    if (cx->hasfp() && cx->fp()->isFunctionFrame() && cx->fp()->fun()->isInterpreted()) {
-        if (report) {
-            /*
-             * N.B. if we can't report errors then cx->compartment may not be
-             * consistent with the function's compartment (cross-compartment
-             * call or SaveFrameChain). In such cases the caller must have
-             * already expanded inline frames.
-             */
-            cx->fp()->fun()->script()->uninlineable = true;
-            types::MarkTypeObjectFlags(cx, cx->fp()->fun(),
-                                       types::OBJECT_FLAG_UNINLINEABLE);
+    if (cx->hasfp() && report) {
+        JSFunction *fun = NULL;
+        if (cx->regs().inlined())
+            fun = cx->fp()->jit()->inlineFrames()[cx->regs().inlined()->inlineIndex].fun;
+        else if (cx->fp()->isFunctionFrame() && cx->fp()->fun()->isInterpreted())
+            fun = cx->fp()->fun();
+        if (fun) {
+            fun->script()->uninlineable = true;
+            types::MarkTypeObjectFlags(cx, fun, types::OBJECT_FLAG_UNINLINEABLE);
         }
-        JS_ASSERT(!cx->regs().inlined());
     }
+    JS_ASSERT_IF(cx->hasfp(), !cx->regs().inlined());
 #endif
 
     if (onTop() && extend) {
         if (!space().ensureSpace(cx, report, firstUnused, nvars))
             return NULL;
         return firstUnused;
     }