Title: [149404] trunk
Revision
149404
Author
[email protected]
Date
2013-04-30 15:15:47 -0700 (Tue, 30 Apr 2013)

Log Message

JSC Stack walking logic craches in the face of inlined functions triggering VM re-entry
https://bugs.webkit.org/show_bug.cgi?id=115449

Reviewed by Geoffrey Garen.

Source/_javascript_Core:

Rename callframeishost to something that makes sense, and fix
getCallerInfo to correctly handle inline functions calling into
the VM.

* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::codeOriginForReturn):
  Make this more robust in the face of incorrect stack walking
* interpreter/CallFrame.cpp:
(JSC::CallFrame::trueCallerFrame):
  Everyone has to perform a codeblock() check before calling this
  so we might as well just do it here.
* interpreter/Interpreter.cpp:
(JSC::getCallerInfo):

LayoutTests:

Add tests

* fast/js/script-tests/stack-trace.js:
(dfgTest):
(inlineableThrow):
(dfgThing.get willThrow):
(dfgThing.get willThrowEventually):
(dfgThing.willThrowFunc):
(dfgThing.willThrowEventuallyFunc):
(dfg1):
(dfg2):
(dfg3):
(dfg4):
(dfg5):
(dfg6):
(dfg7):
(dfg8):
(dfg9):
(dfga):
(dfgb):
(dfgc):
* fast/js/stack-trace-expected.txt:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (149403 => 149404)


--- trunk/LayoutTests/ChangeLog	2013-04-30 22:10:51 UTC (rev 149403)
+++ trunk/LayoutTests/ChangeLog	2013-04-30 22:15:47 UTC (rev 149404)
@@ -1,3 +1,33 @@
+2013-04-30  Oliver Hunt  <[email protected]>
+
+        JSC Stack walking logic craches in the face of inlined functions triggering VM re-entry
+        https://bugs.webkit.org/show_bug.cgi?id=115449
+
+        Reviewed by Geoffrey Garen.
+
+        Add tests
+
+        * fast/js/script-tests/stack-trace.js:
+        (dfgTest):
+        (inlineableThrow):
+        (dfgThing.get willThrow):
+        (dfgThing.get willThrowEventually):
+        (dfgThing.willThrowFunc):
+        (dfgThing.willThrowEventuallyFunc):
+        (dfg1):
+        (dfg2):
+        (dfg3):
+        (dfg4):
+        (dfg5):
+        (dfg6):
+        (dfg7):
+        (dfg8):
+        (dfg9):
+        (dfga):
+        (dfgb):
+        (dfgc):
+        * fast/js/stack-trace-expected.txt:
+
 2013-04-30  Roger Fong  <[email protected]>
 
         Unreviewed. Rebaseline some tests on AppleWin port after disabling subpixel layout.

Modified: trunk/LayoutTests/fast/js/script-tests/stack-trace.js (149403 => 149404)


--- trunk/LayoutTests/fast/js/script-tests/stack-trace.js	2013-04-30 22:10:51 UTC (rev 149403)
+++ trunk/LayoutTests/fast/js/script-tests/stack-trace.js	2013-04-30 22:15:47 UTC (rev 149404)
@@ -224,4 +224,86 @@
     }
 }
 
+function dfgTest(f) {
+    dfgCount = 0;
+    while (dfgCount++ < 1000) {
+        try {
+            f();
+        } catch (e) {
+            printStack(e.stack)
+            return;
+        }
+    }
+}
+
+function inlineableThrow() {
+    if (dfgCount > 500) throw {};
+}
+
+var dfgThing = {
+    get willThrow() {
+        if (dfgCount > 500)
+            throw {};
+    },
+    get willThrowEventually() {
+        inlineableThrow();
+    },
+    willThrowFunc: function () { if (dfgCount > 500) throw {}; },
+    willThrowEventuallyFunc: function () { inlineableThrow(); }
+}
+dfgThing.__defineGetter__("hostWillThrow", hostThrower);
+
+function dfg1() {
+    dfgThing.willThrow
+}
+
+function dfg2() {
+    dfg1();
+}
+
+function dfg3() {
+    dfg2();
+}
+
+function dfg4() {
+    dfgThing.willThrowFunc();
+}
+
+function dfg5() {
+    dfg4();
+}
+
+function dfg6() {
+    dfg5();
+}
+
+function dfg7() {
+    dfgThing.willThrowEventually
+}
+
+function dfg8() {
+    dfg7();
+}
+
+function dfg9() {
+    dfg8();
+}
+
+function dfga() {
+    dfgThing.willThrowEventuallyFunc();
+}
+
+function dfgb() {
+    dfga();
+}
+
+function dfgc() {
+    dfgb();
+}
+
+dfgTest(dfg3)
+dfgTest(dfg6)
+dfgTest(dfg9)
+dfgTest(dfgc)
+
 successfullyParsed = true;

Modified: trunk/LayoutTests/fast/js/stack-trace-expected.txt (149403 => 149404)


--- trunk/LayoutTests/fast/js/stack-trace-expected.txt	2013-04-30 22:10:51 UTC (rev 149403)
+++ trunk/LayoutTests/fast/js/stack-trace-expected.txt	2013-04-30 22:15:47 UTC (rev 149404)
@@ -427,4 +427,38 @@
     2   f at stack-trace.js:202:9
     3   global code at stack-trace.js:208:5
 
+--> Stack Trace:
+    0   willThrow at stack-trace.js:246:20
+    1   dfg1 at stack-trace.js:257:12
+    2   dfg2 at stack-trace.js:261:8
+    3   dfg3 at stack-trace.js:265:8
+    4   dfgTest at stack-trace.js:231:13
+    5   global code at stack-trace.js:304:7
 
+--> Stack Trace:
+    0   willThrowFunc at stack-trace.js:251:61
+    1   dfg4 at stack-trace.js:269:26
+    2   dfg5 at stack-trace.js:273:8
+    3   dfg6 at stack-trace.js:277:8
+    4   dfgTest at stack-trace.js:231:13
+    5   global code at stack-trace.js:305:7
+
+--> Stack Trace:
+    0   inlineableThrow at stack-trace.js:240:32
+    1   willThrowEventually at stack-trace.js:249:23
+    2   dfg7 at stack-trace.js:281:12
+    3   dfg8 at stack-trace.js:285:8
+    4   dfg9 at stack-trace.js:289:8
+    5   dfgTest at stack-trace.js:231:13
+    6   global code at stack-trace.js:306:7
+
+--> Stack Trace:
+    0   inlineableThrow at stack-trace.js:240:32
+    1   willThrowEventuallyFunc at stack-trace.js:252:58
+    2   dfga at stack-trace.js:293:36
+    3   dfgb at stack-trace.js:297:8
+    4   dfgc at stack-trace.js:301:8
+    5   dfgTest at stack-trace.js:231:13
+    6   global code at stack-trace.js:307:7
+
+

Modified: trunk/Source/_javascript_Core/ChangeLog (149403 => 149404)


--- trunk/Source/_javascript_Core/ChangeLog	2013-04-30 22:10:51 UTC (rev 149403)
+++ trunk/Source/_javascript_Core/ChangeLog	2013-04-30 22:15:47 UTC (rev 149404)
@@ -1,3 +1,24 @@
+2013-04-30  Oliver Hunt  <[email protected]>
+
+        JSC Stack walking logic craches in the face of inlined functions triggering VM re-entry
+        https://bugs.webkit.org/show_bug.cgi?id=115449
+
+        Reviewed by Geoffrey Garen.
+
+        Rename callframeishost to something that makes sense, and fix
+        getCallerInfo to correctly handle inline functions calling into
+        the VM.
+
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::codeOriginForReturn):
+          Make this more robust in the face of incorrect stack walking
+        * interpreter/CallFrame.cpp:
+        (JSC::CallFrame::trueCallerFrame):
+          Everyone has to perform a codeblock() check before calling this
+          so we might as well just do it here.
+        * interpreter/Interpreter.cpp:
+        (JSC::getCallerInfo):
+
 2013-04-30  Julien Brianceau  <[email protected]>
 
         Bug fixing in sh4 base JIT and LLINT.

Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp (149403 => 149404)


--- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2013-04-30 22:10:51 UTC (rev 149403)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2013-04-30 22:15:47 UTC (rev 149404)
@@ -2747,7 +2747,11 @@
         return false;
 
     if (!getJITCode().getExecutableMemory()->contains(returnAddress.value())) {
-        codeOrigin = findClosureCallForReturnPC(returnAddress)->codeOrigin();
+        ClosureCallStubRoutine* stub = findClosureCallForReturnPC(returnAddress);
+        ASSERT(stub);
+        if (!stub)
+            return false;
+        codeOrigin = stub->codeOrigin();
         return true;
     }
     

Modified: trunk/Source/_javascript_Core/interpreter/CallFrame.cpp (149403 => 149404)


--- trunk/Source/_javascript_Core/interpreter/CallFrame.cpp	2013-04-30 22:10:51 UTC (rev 149403)
+++ trunk/Source/_javascript_Core/interpreter/CallFrame.cpp	2013-04-30 22:15:47 UTC (rev 149404)
@@ -172,6 +172,9 @@
         
 CallFrame* CallFrame::trueCallerFrame()
 {
+    if (!codeBlock())
+        return callerFrame()->removeHostCallFrameFlag();
+
     // this -> The callee; this is either an inlined callee in which case it already has
     //    a pointer to the true caller. Otherwise it contains current PC in the machine
     //    caller.

Modified: trunk/Source/_javascript_Core/interpreter/Interpreter.cpp (149403 => 149404)


--- trunk/Source/_javascript_Core/interpreter/Interpreter.cpp	2013-04-30 22:10:51 UTC (rev 149403)
+++ trunk/Source/_javascript_Core/interpreter/Interpreter.cpp	2013-04-30 22:15:47 UTC (rev 149404)
@@ -520,41 +520,33 @@
     ASSERT_UNUSED(vm, vm);
     bytecodeOffset = 0;
     ASSERT(!callFrame->hasHostCallFrameFlag());
-    CallFrame* callerFrame = callFrame->codeBlock() ? callFrame->trueCallerFrame() : callFrame->callerFrame()->removeHostCallFrameFlag();
-    bool callframeIsHost = callerFrame->addHostCallFrameFlag() == callFrame->callerFrame();
-    ASSERT(!callerFrame->hasHostCallFrameFlag());
+    CallFrame* trueCallerFrame = callFrame->trueCallerFrame();
+    bool wasCalledByHost = callFrame->callerFrame()->hasHostCallFrameFlag();
+    ASSERT(!trueCallerFrame->hasHostCallFrameFlag());
 
-    if (callerFrame == CallFrame::noCaller() || !callerFrame || !callerFrame->codeBlock()) {
+    if (trueCallerFrame == CallFrame::noCaller() || !trueCallerFrame || !trueCallerFrame->codeBlock()) {
         caller = 0;
-        return callerFrame;
+        return trueCallerFrame;
     }
     
-    CodeBlock* callerCodeBlock = callerFrame->codeBlock();
+    CodeBlock* callerCodeBlock = trueCallerFrame->codeBlock();
     
-#if ENABLE(JIT) || ENABLE(LLINT)
     if (!callFrame->hasReturnPC())
-        callframeIsHost = true;
-#endif
-#if ENABLE(DFG_JIT)
-    if (callFrame->isInlineCallFrame())
-        callframeIsHost = false;
-#endif
+        wasCalledByHost = true;
 
-    if (callframeIsHost) {
-        // Don't need to deal with inline callframes here as by definition we haven't
-        // inlined a call with an intervening native call frame.
-#if ENABLE(JIT) || ENABLE(LLINT)
+    if (wasCalledByHost) {
 #if ENABLE(DFG_JIT)
         if (callerCodeBlock && callerCodeBlock->getJITType() == JITCode::DFGJIT) {
-            unsigned codeOriginIndex = callerFrame->codeOriginIndexForDFG();
-            bytecodeOffset = callerCodeBlock->codeOrigin(codeOriginIndex).bytecodeIndex;
+            unsigned codeOriginIndex = callFrame->callerFrame()->removeHostCallFrameFlag()->codeOriginIndexForDFG();
+            CodeOrigin origin = callerCodeBlock->codeOrigin(codeOriginIndex);
+            bytecodeOffset = origin.bytecodeIndex;
+            if (InlineCallFrame* inlineCallFrame = origin.inlineCallFrame)
+                callerCodeBlock = inlineCallFrame->baselineCodeBlock();
         } else
 #endif
-            bytecodeOffset = callerFrame->bytecodeOffsetForNonDFGCode();
-#endif
+            bytecodeOffset = trueCallerFrame->bytecodeOffsetForNonDFGCode();
     } else {
-#if ENABLE(JIT) || ENABLE(LLINT)
-    #if ENABLE(DFG_JIT)
+#if ENABLE(DFG_JIT)
         if (callFrame->isInlineCallFrame()) {
             InlineCallFrame* icf = callFrame->inlineCallFrame();
             bytecodeOffset = icf->caller.bytecodeIndex;
@@ -584,17 +576,16 @@
                 callerCodeBlock = newCodeBlock;
             }
         } else
-    #endif
+#endif
         {
             RELEASE_ASSERT(callerCodeBlock);
-            bytecodeOffset = callerCodeBlock->bytecodeOffset(callerFrame, callFrame->returnPC());
+            bytecodeOffset = callerCodeBlock->bytecodeOffset(trueCallerFrame, callFrame->returnPC());
         }
-#endif
     }
 
     RELEASE_ASSERT(callerCodeBlock);
     caller = callerCodeBlock;
-    return callerFrame;
+    return trueCallerFrame;
 }
 
 static ALWAYS_INLINE const String getSourceURLFromCallFrame(CallFrame* callFrame)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to