Exception stack traces aren't complete when the exception starts in native code
authoroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 16 Apr 2012 22:26:36 +0000 (22:26 +0000)
committeroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 16 Apr 2012 22:26:36 +0000 (22:26 +0000)
https://bugs.webkit.org/show_bug.cgi?id=84073

Reviewed by Gavin Barraclough.

Source/JavaScriptCore:

Refactored building the stack trace to so that we can construct
it earlier, and don't rely on any prior work performed in the
exception handling machinery. Also updated LLInt and the DFG to
completely initialise the callframes of host function calls.

* bytecode/CodeBlock.h:
(JSC::CodeBlock::codeOriginIndexForReturn):
(CodeBlock):
* dfg/DFGOperations.cpp:
* interpreter/Interpreter.cpp:
(JSC::Interpreter::getStackTrace):
(JSC::Interpreter::addStackTraceIfNecessary):
(JSC):
(JSC::Interpreter::throwException):
* interpreter/Interpreter.h:
(Interpreter):
* jit/JITStubs.cpp:
(JSC::DEFINE_STUB_FUNCTION):
* jsc.cpp:
(functionJSCStack):
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::handleHostCall):
* parser/Parser.h:
(JSC::::parse):
* runtime/Error.cpp:
(JSC::addErrorInfo):
(JSC::throwError):
* runtime/Error.h:
(JSC):

LayoutTests:

Update tests to include new exception property ordering, and new functions

* fast/js/exception-properties-expected.txt:
* fast/js/script-tests/exception-properties.js:
* fast/js/script-tests/stack-trace.js:
(selfRecursive1): Modified slightly so that we produce consistent traces
* fast/js/stack-trace-expected.txt:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@114309 268f45cc-cd09-0410-ab3c-d52691b4dbfc

17 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/js/exception-properties-expected.txt
LayoutTests/fast/js/script-tests/exception-properties.js
LayoutTests/fast/js/script-tests/stack-trace.js
LayoutTests/fast/js/stack-trace-expected.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
Source/JavaScriptCore/bytecode/CodeBlock.h
Source/JavaScriptCore/dfg/DFGOperations.cpp
Source/JavaScriptCore/interpreter/Interpreter.cpp
Source/JavaScriptCore/interpreter/Interpreter.h
Source/JavaScriptCore/jit/JITStubs.cpp
Source/JavaScriptCore/jsc.cpp
Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
Source/JavaScriptCore/parser/Parser.h
Source/JavaScriptCore/runtime/Error.cpp
Source/JavaScriptCore/runtime/Error.h

index 1e1ff37..2a82d9d 100644 (file)
@@ -1,3 +1,18 @@
+2012-04-16  Oliver Hunt  <oliver@apple.com>
+
+        Exception stack traces aren't complete when the exception starts in native code
+        https://bugs.webkit.org/show_bug.cgi?id=84073
+
+        Reviewed by Gavin Barraclough.
+
+        Update tests to include new exception property ordering, and new functions
+
+        * fast/js/exception-properties-expected.txt:
+        * fast/js/script-tests/exception-properties.js:
+        * fast/js/script-tests/stack-trace.js:
+        (selfRecursive1): Modified slightly so that we produce consistent traces
+        * fast/js/stack-trace-expected.txt:
+
 2012-04-16  David Alcala  <dalcala@adobe.com>
 
         Update test_expectations for chromium
index 5363e04..5d9943a 100644 (file)
@@ -4,7 +4,7 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
 
 
 PASS enumerableProperties(error) is []
-PASS enumerableProperties(nativeError) is ["line", "sourceURL", "stack"]
+PASS enumerableProperties(nativeError) is ["stack", "line", "sourceURL"]
 PASS Object.getPrototypeOf(nativeError).name is "RangeError"
 PASS Object.getPrototypeOf(nativeError).message is ""
 PASS successfullyParsed is true
index 19eb345..43e1153 100644 (file)
@@ -16,7 +16,7 @@ try {
     var error = new Error("message");
 
     shouldBe('enumerableProperties(error)', '[]');
-    shouldBe('enumerableProperties(nativeError)', '["line", "sourceURL", "stack"]');
+    shouldBe('enumerableProperties(nativeError)', '["stack", "line", "sourceURL"]');
 
     shouldBe('Object.getPrototypeOf(nativeError).name', '"RangeError"');
     shouldBe('Object.getPrototypeOf(nativeError).message', '""');
index 04736bb..9abf997 100644 (file)
@@ -49,10 +49,10 @@ try { hostThrower(); } catch (e) { printStack(e.stack); }                    //
 try { scripterInner(); } catch (e) { printStack(e.stack) }                   // program -> scripter -> inner
 try { scripterOuter(); } catch (e) { printStack(e.stack) }                   // program -> scripter -> outer -> inner
 
-function selfRecursive1() {
-    selfRecursive1();
+function selfRecursive1() { selfRecursive1();
 }
 
+
 try { selfRecursive1(); } catch (e) { printStack(e.stack) }                   // selfRecursive1 -> selfRecursive1 -> selfRecursive1 -> selfRecursive1 ...
 
 function selfRecursive2() {
index d562b06..f5bf2e7 100644 (file)
@@ -33,8 +33,9 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
     2   global code at stack-trace.js:44
 
 --> Stack Trace:
-    0   hostThrower at stack-trace.js:25
-    1   global code at stack-trace.js:47
+    0   appendChild at [native code]
+    1   hostThrower at stack-trace.js:25
+    2   global code at stack-trace.js:47
 
 --> Stack Trace:
     0   htmlInner at stack-trace.html:10
@@ -48,109 +49,109 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
     3   global code at stack-trace.js:50
 
 --> Stack Trace:
-    0   selfRecursive1 at stack-trace.js:53
-    1   selfRecursive1 at stack-trace.js:53
-    2   selfRecursive1 at stack-trace.js:53
-    3   selfRecursive1 at stack-trace.js:53
-    4   selfRecursive1 at stack-trace.js:53
-    5   selfRecursive1 at stack-trace.js:53
-    6   selfRecursive1 at stack-trace.js:53
-    7   selfRecursive1 at stack-trace.js:53
-    8   selfRecursive1 at stack-trace.js:53
-    9   selfRecursive1 at stack-trace.js:53
-    10   selfRecursive1 at stack-trace.js:53
-    11   selfRecursive1 at stack-trace.js:53
-    12   selfRecursive1 at stack-trace.js:53
-    13   selfRecursive1 at stack-trace.js:53
-    14   selfRecursive1 at stack-trace.js:53
-    15   selfRecursive1 at stack-trace.js:53
-    16   selfRecursive1 at stack-trace.js:53
-    17   selfRecursive1 at stack-trace.js:53
-    18   selfRecursive1 at stack-trace.js:53
-    19   selfRecursive1 at stack-trace.js:53
-    20   selfRecursive1 at stack-trace.js:53
-    21   selfRecursive1 at stack-trace.js:53
-    22   selfRecursive1 at stack-trace.js:53
-    23   selfRecursive1 at stack-trace.js:53
-    24   selfRecursive1 at stack-trace.js:53
-    25   selfRecursive1 at stack-trace.js:53
-    26   selfRecursive1 at stack-trace.js:53
-    27   selfRecursive1 at stack-trace.js:53
-    28   selfRecursive1 at stack-trace.js:53
-    29   selfRecursive1 at stack-trace.js:53
-    30   selfRecursive1 at stack-trace.js:53
-    31   selfRecursive1 at stack-trace.js:53
-    32   selfRecursive1 at stack-trace.js:53
-    33   selfRecursive1 at stack-trace.js:53
-    34   selfRecursive1 at stack-trace.js:53
-    35   selfRecursive1 at stack-trace.js:53
-    36   selfRecursive1 at stack-trace.js:53
-    37   selfRecursive1 at stack-trace.js:53
-    38   selfRecursive1 at stack-trace.js:53
-    39   selfRecursive1 at stack-trace.js:53
-    40   selfRecursive1 at stack-trace.js:53
-    41   selfRecursive1 at stack-trace.js:53
-    42   selfRecursive1 at stack-trace.js:53
-    43   selfRecursive1 at stack-trace.js:53
-    44   selfRecursive1 at stack-trace.js:53
-    45   selfRecursive1 at stack-trace.js:53
-    46   selfRecursive1 at stack-trace.js:53
-    47   selfRecursive1 at stack-trace.js:53
-    48   selfRecursive1 at stack-trace.js:53
-    49   selfRecursive1 at stack-trace.js:53
-    50   selfRecursive1 at stack-trace.js:53
-    51   selfRecursive1 at stack-trace.js:53
-    52   selfRecursive1 at stack-trace.js:53
-    53   selfRecursive1 at stack-trace.js:53
-    54   selfRecursive1 at stack-trace.js:53
-    55   selfRecursive1 at stack-trace.js:53
-    56   selfRecursive1 at stack-trace.js:53
-    57   selfRecursive1 at stack-trace.js:53
-    58   selfRecursive1 at stack-trace.js:53
-    59   selfRecursive1 at stack-trace.js:53
-    60   selfRecursive1 at stack-trace.js:53
-    61   selfRecursive1 at stack-trace.js:53
-    62   selfRecursive1 at stack-trace.js:53
-    63   selfRecursive1 at stack-trace.js:53
-    64   selfRecursive1 at stack-trace.js:53
-    65   selfRecursive1 at stack-trace.js:53
-    66   selfRecursive1 at stack-trace.js:53
-    67   selfRecursive1 at stack-trace.js:53
-    68   selfRecursive1 at stack-trace.js:53
-    69   selfRecursive1 at stack-trace.js:53
-    70   selfRecursive1 at stack-trace.js:53
-    71   selfRecursive1 at stack-trace.js:53
-    72   selfRecursive1 at stack-trace.js:53
-    73   selfRecursive1 at stack-trace.js:53
-    74   selfRecursive1 at stack-trace.js:53
-    75   selfRecursive1 at stack-trace.js:53
-    76   selfRecursive1 at stack-trace.js:53
-    77   selfRecursive1 at stack-trace.js:53
-    78   selfRecursive1 at stack-trace.js:53
-    79   selfRecursive1 at stack-trace.js:53
-    80   selfRecursive1 at stack-trace.js:53
-    81   selfRecursive1 at stack-trace.js:53
-    82   selfRecursive1 at stack-trace.js:53
-    83   selfRecursive1 at stack-trace.js:53
-    84   selfRecursive1 at stack-trace.js:53
-    85   selfRecursive1 at stack-trace.js:53
-    86   selfRecursive1 at stack-trace.js:53
-    87   selfRecursive1 at stack-trace.js:53
-    88   selfRecursive1 at stack-trace.js:53
-    89   selfRecursive1 at stack-trace.js:53
-    90   selfRecursive1 at stack-trace.js:53
-    91   selfRecursive1 at stack-trace.js:53
-    92   selfRecursive1 at stack-trace.js:53
-    93   selfRecursive1 at stack-trace.js:53
-    94   selfRecursive1 at stack-trace.js:53
-    95   selfRecursive1 at stack-trace.js:53
-    96   selfRecursive1 at stack-trace.js:53
-    97   selfRecursive1 at stack-trace.js:53
-    98   selfRecursive1 at stack-trace.js:53
-    99   selfRecursive1 at stack-trace.js:53
+    0   selfRecursive1 at stack-trace.js:52
+    1   selfRecursive1 at stack-trace.js:52
+    2   selfRecursive1 at stack-trace.js:52
+    3   selfRecursive1 at stack-trace.js:52
+    4   selfRecursive1 at stack-trace.js:52
+    5   selfRecursive1 at stack-trace.js:52
+    6   selfRecursive1 at stack-trace.js:52
+    7   selfRecursive1 at stack-trace.js:52
+    8   selfRecursive1 at stack-trace.js:52
+    9   selfRecursive1 at stack-trace.js:52
+    10   selfRecursive1 at stack-trace.js:52
+    11   selfRecursive1 at stack-trace.js:52
+    12   selfRecursive1 at stack-trace.js:52
+    13   selfRecursive1 at stack-trace.js:52
+    14   selfRecursive1 at stack-trace.js:52
+    15   selfRecursive1 at stack-trace.js:52
+    16   selfRecursive1 at stack-trace.js:52
+    17   selfRecursive1 at stack-trace.js:52
+    18   selfRecursive1 at stack-trace.js:52
+    19   selfRecursive1 at stack-trace.js:52
+    20   selfRecursive1 at stack-trace.js:52
+    21   selfRecursive1 at stack-trace.js:52
+    22   selfRecursive1 at stack-trace.js:52
+    23   selfRecursive1 at stack-trace.js:52
+    24   selfRecursive1 at stack-trace.js:52
+    25   selfRecursive1 at stack-trace.js:52
+    26   selfRecursive1 at stack-trace.js:52
+    27   selfRecursive1 at stack-trace.js:52
+    28   selfRecursive1 at stack-trace.js:52
+    29   selfRecursive1 at stack-trace.js:52
+    30   selfRecursive1 at stack-trace.js:52
+    31   selfRecursive1 at stack-trace.js:52
+    32   selfRecursive1 at stack-trace.js:52
+    33   selfRecursive1 at stack-trace.js:52
+    34   selfRecursive1 at stack-trace.js:52
+    35   selfRecursive1 at stack-trace.js:52
+    36   selfRecursive1 at stack-trace.js:52
+    37   selfRecursive1 at stack-trace.js:52
+    38   selfRecursive1 at stack-trace.js:52
+    39   selfRecursive1 at stack-trace.js:52
+    40   selfRecursive1 at stack-trace.js:52
+    41   selfRecursive1 at stack-trace.js:52
+    42   selfRecursive1 at stack-trace.js:52
+    43   selfRecursive1 at stack-trace.js:52
+    44   selfRecursive1 at stack-trace.js:52
+    45   selfRecursive1 at stack-trace.js:52
+    46   selfRecursive1 at stack-trace.js:52
+    47   selfRecursive1 at stack-trace.js:52
+    48   selfRecursive1 at stack-trace.js:52
+    49   selfRecursive1 at stack-trace.js:52
+    50   selfRecursive1 at stack-trace.js:52
+    51   selfRecursive1 at stack-trace.js:52
+    52   selfRecursive1 at stack-trace.js:52
+    53   selfRecursive1 at stack-trace.js:52
+    54   selfRecursive1 at stack-trace.js:52
+    55   selfRecursive1 at stack-trace.js:52
+    56   selfRecursive1 at stack-trace.js:52
+    57   selfRecursive1 at stack-trace.js:52
+    58   selfRecursive1 at stack-trace.js:52
+    59   selfRecursive1 at stack-trace.js:52
+    60   selfRecursive1 at stack-trace.js:52
+    61   selfRecursive1 at stack-trace.js:52
+    62   selfRecursive1 at stack-trace.js:52
+    63   selfRecursive1 at stack-trace.js:52
+    64   selfRecursive1 at stack-trace.js:52
+    65   selfRecursive1 at stack-trace.js:52
+    66   selfRecursive1 at stack-trace.js:52
+    67   selfRecursive1 at stack-trace.js:52
+    68   selfRecursive1 at stack-trace.js:52
+    69   selfRecursive1 at stack-trace.js:52
+    70   selfRecursive1 at stack-trace.js:52
+    71   selfRecursive1 at stack-trace.js:52
+    72   selfRecursive1 at stack-trace.js:52
+    73   selfRecursive1 at stack-trace.js:52
+    74   selfRecursive1 at stack-trace.js:52
+    75   selfRecursive1 at stack-trace.js:52
+    76   selfRecursive1 at stack-trace.js:52
+    77   selfRecursive1 at stack-trace.js:52
+    78   selfRecursive1 at stack-trace.js:52
+    79   selfRecursive1 at stack-trace.js:52
+    80   selfRecursive1 at stack-trace.js:52
+    81   selfRecursive1 at stack-trace.js:52
+    82   selfRecursive1 at stack-trace.js:52
+    83   selfRecursive1 at stack-trace.js:52
+    84   selfRecursive1 at stack-trace.js:52
+    85   selfRecursive1 at stack-trace.js:52
+    86   selfRecursive1 at stack-trace.js:52
+    87   selfRecursive1 at stack-trace.js:52
+    88   selfRecursive1 at stack-trace.js:52
+    89   selfRecursive1 at stack-trace.js:52
+    90   selfRecursive1 at stack-trace.js:52
+    91   selfRecursive1 at stack-trace.js:52
+    92   selfRecursive1 at stack-trace.js:52
+    93   selfRecursive1 at stack-trace.js:52
+    94   selfRecursive1 at stack-trace.js:52
+    95   selfRecursive1 at stack-trace.js:52
+    96   selfRecursive1 at stack-trace.js:52
+    97   selfRecursive1 at stack-trace.js:52
+    98   selfRecursive1 at stack-trace.js:52
+    99   selfRecursive1 at stack-trace.js:52
 
 --> Stack Trace:
-    0   selfRecursive2 at stack-trace.js:62
+    0   selfRecursive2 at stack-trace.js:58
     1   selfRecursive2 at stack-trace.js:62
     2   selfRecursive2 at stack-trace.js:62
     3   selfRecursive2 at stack-trace.js:62
@@ -252,106 +253,106 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
     99   selfRecursive2 at stack-trace.js:62
 
 --> Stack Trace:
-    0   selfRecursive3 at stack-trace.js:69
-    1    at eval code
-    2   eval at [native code]
-    3   selfRecursive3 at stack-trace.js:69
-    4    at eval code
-    5   eval at [native code]
-    6   selfRecursive3 at stack-trace.js:69
-    7    at eval code
-    8   eval at [native code]
-    9   selfRecursive3 at stack-trace.js:69
-    10    at eval code
-    11   eval at [native code]
-    12   selfRecursive3 at stack-trace.js:69
-    13    at eval code
-    14   eval at [native code]
-    15   selfRecursive3 at stack-trace.js:69
-    16    at eval code
-    17   eval at [native code]
-    18   selfRecursive3 at stack-trace.js:69
-    19    at eval code
-    20   eval at [native code]
-    21   selfRecursive3 at stack-trace.js:69
-    22    at eval code
-    23   eval at [native code]
-    24   selfRecursive3 at stack-trace.js:69
-    25    at eval code
-    26   eval at [native code]
-    27   selfRecursive3 at stack-trace.js:69
-    28    at eval code
-    29   eval at [native code]
-    30   selfRecursive3 at stack-trace.js:69
-    31    at eval code
-    32   eval at [native code]
-    33   selfRecursive3 at stack-trace.js:69
-    34    at eval code
-    35   eval at [native code]
-    36   selfRecursive3 at stack-trace.js:69
-    37    at eval code
-    38   eval at [native code]
-    39   selfRecursive3 at stack-trace.js:69
-    40    at eval code
-    41   eval at [native code]
-    42   selfRecursive3 at stack-trace.js:69
-    43    at eval code
-    44   eval at [native code]
-    45   selfRecursive3 at stack-trace.js:69
-    46    at eval code
-    47   eval at [native code]
-    48   selfRecursive3 at stack-trace.js:69
-    49    at eval code
-    50   eval at [native code]
-    51   selfRecursive3 at stack-trace.js:69
-    52    at eval code
-    53   eval at [native code]
-    54   selfRecursive3 at stack-trace.js:69
-    55    at eval code
-    56   eval at [native code]
-    57   selfRecursive3 at stack-trace.js:69
-    58    at eval code
-    59   eval at [native code]
-    60   selfRecursive3 at stack-trace.js:69
-    61    at eval code
-    62   eval at [native code]
-    63   selfRecursive3 at stack-trace.js:69
-    64    at eval code
-    65   eval at [native code]
-    66   selfRecursive3 at stack-trace.js:69
-    67    at eval code
-    68   eval at [native code]
-    69   selfRecursive3 at stack-trace.js:69
-    70    at eval code
-    71   eval at [native code]
-    72   selfRecursive3 at stack-trace.js:69
-    73    at eval code
-    74   eval at [native code]
-    75   selfRecursive3 at stack-trace.js:69
-    76    at eval code
-    77   eval at [native code]
-    78   selfRecursive3 at stack-trace.js:69
-    79    at eval code
-    80   eval at [native code]
-    81   selfRecursive3 at stack-trace.js:69
-    82    at eval code
-    83   eval at [native code]
-    84   selfRecursive3 at stack-trace.js:69
-    85    at eval code
-    86   eval at [native code]
-    87   selfRecursive3 at stack-trace.js:69
-    88    at eval code
-    89   eval at [native code]
-    90   selfRecursive3 at stack-trace.js:69
-    91    at eval code
-    92   eval at [native code]
-    93   selfRecursive3 at stack-trace.js:69
-    94    at eval code
-    95   eval at [native code]
-    96   selfRecursive3 at stack-trace.js:69
-    97    at eval code
-    98   eval at [native code]
-    99   selfRecursive3 at stack-trace.js:69
+    0   eval at [native code]
+    1   selfRecursive3 at stack-trace.js:69
+    2    at eval code
+    3   eval at [native code]
+    4   selfRecursive3 at stack-trace.js:69
+    5    at eval code
+    6   eval at [native code]
+    7   selfRecursive3 at stack-trace.js:69
+    8    at eval code
+    9   eval at [native code]
+    10   selfRecursive3 at stack-trace.js:69
+    11    at eval code
+    12   eval at [native code]
+    13   selfRecursive3 at stack-trace.js:69
+    14    at eval code
+    15   eval at [native code]
+    16   selfRecursive3 at stack-trace.js:69
+    17    at eval code
+    18   eval at [native code]
+    19   selfRecursive3 at stack-trace.js:69
+    20    at eval code
+    21   eval at [native code]
+    22   selfRecursive3 at stack-trace.js:69
+    23    at eval code
+    24   eval at [native code]
+    25   selfRecursive3 at stack-trace.js:69
+    26    at eval code
+    27   eval at [native code]
+    28   selfRecursive3 at stack-trace.js:69
+    29    at eval code
+    30   eval at [native code]
+    31   selfRecursive3 at stack-trace.js:69
+    32    at eval code
+    33   eval at [native code]
+    34   selfRecursive3 at stack-trace.js:69
+    35    at eval code
+    36   eval at [native code]
+    37   selfRecursive3 at stack-trace.js:69
+    38    at eval code
+    39   eval at [native code]
+    40   selfRecursive3 at stack-trace.js:69
+    41    at eval code
+    42   eval at [native code]
+    43   selfRecursive3 at stack-trace.js:69
+    44    at eval code
+    45   eval at [native code]
+    46   selfRecursive3 at stack-trace.js:69
+    47    at eval code
+    48   eval at [native code]
+    49   selfRecursive3 at stack-trace.js:69
+    50    at eval code
+    51   eval at [native code]
+    52   selfRecursive3 at stack-trace.js:69
+    53    at eval code
+    54   eval at [native code]
+    55   selfRecursive3 at stack-trace.js:69
+    56    at eval code
+    57   eval at [native code]
+    58   selfRecursive3 at stack-trace.js:69
+    59    at eval code
+    60   eval at [native code]
+    61   selfRecursive3 at stack-trace.js:69
+    62    at eval code
+    63   eval at [native code]
+    64   selfRecursive3 at stack-trace.js:69
+    65    at eval code
+    66   eval at [native code]
+    67   selfRecursive3 at stack-trace.js:69
+    68    at eval code
+    69   eval at [native code]
+    70   selfRecursive3 at stack-trace.js:69
+    71    at eval code
+    72   eval at [native code]
+    73   selfRecursive3 at stack-trace.js:69
+    74    at eval code
+    75   eval at [native code]
+    76   selfRecursive3 at stack-trace.js:69
+    77    at eval code
+    78   eval at [native code]
+    79   selfRecursive3 at stack-trace.js:69
+    80    at eval code
+    81   eval at [native code]
+    82   selfRecursive3 at stack-trace.js:69
+    83    at eval code
+    84   eval at [native code]
+    85   selfRecursive3 at stack-trace.js:69
+    86    at eval code
+    87   eval at [native code]
+    88   selfRecursive3 at stack-trace.js:69
+    89    at eval code
+    90   eval at [native code]
+    91   selfRecursive3 at stack-trace.js:69
+    92    at eval code
+    93   eval at [native code]
+    94   selfRecursive3 at stack-trace.js:69
+    95    at eval code
+    96   eval at [native code]
+    97   selfRecursive3 at stack-trace.js:69
+    98    at eval code
+    99   eval at [native code]
 
 --> Stack Trace:
     0   throwError at stack-trace.js:77
@@ -407,11 +408,12 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
     4   global code at stack-trace.js:169
 
 --> Stack Trace:
-    0   h at stack-trace.js:153
-    1   map at [native code]
-    2   mapTest at stack-trace.js:158
-    3   mapTestDriver at stack-trace.js:164
-    4   global code at stack-trace.js:175
+    0   map at [native code]
+    1   h at stack-trace.js:153
+    2   map at [native code]
+    3   mapTest at stack-trace.js:158
+    4   mapTestDriver at stack-trace.js:164
+    5   global code at stack-trace.js:175
 
 --> Stack Trace:
     0   throwError at stack-trace.js:77
index 1ea1b2e..c4144a6 100644 (file)
@@ -1,5 +1,42 @@
 2012-04-16  Oliver Hunt  <oliver@apple.com>
 
+        Exception stack traces aren't complete when the exception starts in native code
+        https://bugs.webkit.org/show_bug.cgi?id=84073
+
+        Reviewed by Gavin Barraclough.
+
+        Refactored building the stack trace to so that we can construct
+        it earlier, and don't rely on any prior work performed in the
+        exception handling machinery. Also updated LLInt and the DFG to
+        completely initialise the callframes of host function calls.
+
+        * bytecode/CodeBlock.h:
+        (JSC::CodeBlock::codeOriginIndexForReturn):
+        (CodeBlock):
+        * dfg/DFGOperations.cpp:
+        * interpreter/Interpreter.cpp:
+        (JSC::Interpreter::getStackTrace):
+        (JSC::Interpreter::addStackTraceIfNecessary):
+        (JSC):
+        (JSC::Interpreter::throwException):
+        * interpreter/Interpreter.h:
+        (Interpreter):
+        * jit/JITStubs.cpp:
+        (JSC::DEFINE_STUB_FUNCTION):
+        * jsc.cpp:
+        (functionJSCStack):
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::handleHostCall):
+        * parser/Parser.h:
+        (JSC::::parse):
+        * runtime/Error.cpp:
+        (JSC::addErrorInfo):
+        (JSC::throwError):
+        * runtime/Error.h:
+        (JSC):
+
+2012-04-16  Oliver Hunt  <oliver@apple.com>
+
         Fix COMMANDLINE_TYPEDARRAYS build
         https://bugs.webkit.org/show_bug.cgi?id=84051
 
index 8482f3f..590915c 100755 (executable)
@@ -212,7 +212,7 @@ EXPORTS
     ?getPropertyDescriptor@JSObject@JSC@@QAE_NPAVExecState@2@ABVIdentifier@2@AAVPropertyDescriptor@2@@Z
     ?getPropertyNames@JSObject@JSC@@SAXPAV12@PAVExecState@2@AAVPropertyNameArray@2@W4EnumerationMode@2@@Z
     ?getSlice@ArgList@JSC@@QBEXHAAV12@@Z
-    ?getStackTrace@Interpreter@JSC@@SAXPAVJSGlobalData@2@HAAV?$Vector@UStackFrame@JSC@@$0A@@WTF@@@Z
+    ?getStackTrace@Interpreter@JSC@@SAXPAVJSGlobalData@2@AAV?$Vector@UStackFrame@JSC@@$0A@@WTF@@@Z
     ?getString@JSCell@JSC@@QBE?AVUString@2@PAVExecState@2@@Z
     ?getString@JSCell@JSC@@QBE_NPAVExecState@2@AAVUString@2@@Z
     ?getter@PropertyDescriptor@JSC@@QBE?AVJSValue@2@XZ
index 778376f..68db90f 100644 (file)
@@ -710,6 +710,14 @@ namespace JSC {
             return true;
         }
         
+        int codeOriginIndexForReturn(ReturnAddressPtr returnAddress)
+        {
+            ASSERT(hasCodeOrigins());
+            unsigned offset = getJITCode().offsetOf(returnAddress.value());
+            CodeOriginAtCallReturnOffset* entry = binarySearch<CodeOriginAtCallReturnOffset, unsigned, getCallReturnOffsetForCodeOrigin>(codeOrigins().begin(), codeOrigins().size(), offset, WTF::KeyMustNotBePresentInArray);
+            return entry - codeOrigins().begin();
+        }
+        
         CodeOrigin codeOrigin(unsigned index)
         {
             ASSERT(m_rareData);
index 4cc2e86..ac8eb80 100644 (file)
@@ -792,6 +792,7 @@ static void* handleHostCall(ExecState* execCallee, JSValue callee, CodeSpecializ
         ASSERT(callType != CallTypeJS);
     
         if (callType == CallTypeHost) {
+            execCallee->setCallee(asObject(callee));
             globalData->hostCallReturnValue = JSValue::decode(callData.native.function(execCallee));
             if (globalData->exception)
                 return 0;
@@ -812,6 +813,7 @@ static void* handleHostCall(ExecState* execCallee, JSValue callee, CodeSpecializ
     ASSERT(constructType != ConstructTypeJS);
     
     if (constructType == ConstructTypeHost) {
+        execCallee->setCallee(asObject(callee));
         globalData->hostCallReturnValue = JSValue::decode(constructData.native.function(execCallee));
         if (globalData->exception)
             return 0;
index 560146e..bdf8511 100644 (file)
@@ -65,6 +65,7 @@
 #include <limits.h>
 #include <stdio.h>
 #include <wtf/Threading.h>
+#include <wtf/text/StringBuilder.h>
 
 #if ENABLE(JIT)
 #include "JIT.h"
@@ -952,14 +953,14 @@ static StackFrameCodeType getStackFrameCodeType(CallFrame* callFrame)
     return StackFrameGlobalCode;
 }
 
-void Interpreter::getStackTrace(JSGlobalData* globalData, int line, Vector<StackFrame>& results)
+void Interpreter::getStackTrace(JSGlobalData* globalData, Vector<StackFrame>& results)
 {
-    CallFrame* callFrame = globalData->topCallFrame->removeHostCallFrameFlag()->trueCallFrameFromVMCode();
+    CallFrame* callFrame = globalData->topCallFrame->removeHostCallFrameFlag();
     if (!callFrame || callFrame == CallFrame::noCaller()) 
         return;
+    int line = getLineNumberForCallFrame(globalData, callFrame);
 
-    if (line == -1)
-        line = getLineNumberForCallFrame(globalData, callFrame);
+    callFrame = callFrame->trueCallFrameFromVMCode();
 
     while (callFrame && callFrame != CallFrame::noCaller()) {
         UString sourceURL;
@@ -975,6 +976,33 @@ void Interpreter::getStackTrace(JSGlobalData* globalData, int line, Vector<Stack
     }
 }
 
+void Interpreter::addStackTraceIfNecessary(CallFrame* callFrame, JSObject* error)
+{
+    JSGlobalData* globalData = &callFrame->globalData();
+    if (error->hasProperty(callFrame, globalData->propertyNames->stack))
+        return;
+
+    Vector<StackFrame> stackTrace;
+    getStackTrace(&callFrame->globalData(), stackTrace);
+    
+    if (stackTrace.isEmpty())
+        return;
+    
+    JSGlobalObject* globalObject = 0;
+    if (isTerminatedExecutionException(error) || isInterruptedExecutionException(error))
+        globalObject = globalData->dynamicGlobalObject;
+    else
+        globalObject = error->globalObject();
+    StringBuilder builder;
+    for (unsigned i = 0; i < stackTrace.size(); i++) {
+        builder.append(String(stackTrace[i].toString(globalObject->globalExec()).impl()));
+        if (i != stackTrace.size() - 1)
+            builder.append('\n');
+    }
+    
+    error->putDirect(*globalData, globalData->propertyNames->stack, jsString(globalData, UString(builder.toString().impl())), ReadOnly | DontDelete);
+}
+
 NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSValue& exceptionValue, unsigned bytecodeOffset)
 {
     CodeBlock* codeBlock = callFrame->codeBlock();
@@ -990,12 +1018,9 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV
         // Using hasExpressionInfo to imply we are interested in rich exception info.
         if (codeBlock->hasExpressionInfo() && !hasErrorInfo(callFrame, exception)) {
             ASSERT(codeBlock->hasLineInfo());
-
             // FIXME: should only really be adding these properties to VM generated exceptions,
             // but the inspector currently requires these for all thrown objects.
-            Vector<StackFrame> stackTrace;
-            getStackTrace(&callFrame->globalData(), codeBlock->lineNumberForBytecodeOffset(bytecodeOffset), stackTrace);
-            addErrorInfo(callFrame, exception, codeBlock->lineNumberForBytecodeOffset(bytecodeOffset), codeBlock->ownerExecutable()->source(), stackTrace);
+            addErrorInfo(callFrame, exception, codeBlock->lineNumberForBytecodeOffset(bytecodeOffset), codeBlock->ownerExecutable()->source());
         }
 
         isInterrupt = isInterruptedExecutionException(exception) || isTerminatedExecutionException(exception);
index 51881a5..adb23f2 100644 (file)
@@ -222,7 +222,8 @@ namespace JSC {
         NEVER_INLINE HandlerInfo* throwException(CallFrame*&, JSValue&, unsigned bytecodeOffset);
         NEVER_INLINE void debug(CallFrame*, DebugHookID, int firstLine, int lastLine);
         static const UString getTraceLine(CallFrame*, StackFrameCodeType, const UString&, int);
-        JS_EXPORT_PRIVATE static void getStackTrace(JSGlobalData*, int line, Vector<StackFrame>& results);
+        JS_EXPORT_PRIVATE static void getStackTrace(JSGlobalData*, Vector<StackFrame>& results);
+        static void addStackTraceIfNecessary(CallFrame*, JSObject* error);
 
         void dumpSampleData(ExecState* exec);
         void startSampling();
index dbcd50e..0d291b3 100644 (file)
@@ -3518,6 +3518,19 @@ DEFINE_STUB_FUNCTION(void*, vm_throw)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
     JSGlobalData* globalData = stackFrame.globalData;
+    // It's possible for us to reach this point with incorrect origin metadata
+    // if a native function throws an exception after being planted in certain
+    // code paths as the native thunk doesn't can't unwind itself as if it were
+    // a JS function. So we redetermine the correct data here just to be safe.
+    if (CodeBlock* codeBlock = stackFrame.callFrame->codeBlock()) {
+#if ENABLE(DFG_JIT)
+        if (codeBlock->hasCodeOrigins())
+            stackFrame.callFrame->setBytecodeOffsetForNonDFGCode(codeBlock->codeOriginIndexForReturn(globalData->exceptionLocation));
+        else
+#endif
+            if (codeBlock->getJITType() == JITCode::BaselineJIT)
+            stackFrame.callFrame->setBytecodeOffsetForNonDFGCode(codeBlock->bytecodeOffset(stackFrame.callFrame, globalData->exceptionLocation));
+    }
     ExceptionHandler handler = jitThrow(globalData, stackFrame.callFrame, globalData->exception, globalData->exceptionLocation);
     STUB_SET_RETURN_ADDRESS(handler.catchRoutine);
     return handler.callFrame;
index 6cfc1e1..ac0ae2c 100644 (file)
@@ -277,7 +277,7 @@ EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState* exec)
 {
     String trace = "--> Stack trace:\n";
     Vector<StackFrame> stackTrace;
-    Interpreter::getStackTrace(&exec->globalData(), -1, stackTrace);
+    Interpreter::getStackTrace(&exec->globalData(), stackTrace);
     int i = 0;
 
     for (Vector<StackFrame>::iterator iter = stackTrace.begin(); iter < stackTrace.end(); iter++) {
index a1ec1ce..ff2b7c2 100644 (file)
@@ -1241,6 +1241,7 @@ static SlowPathReturnType handleHostCall(ExecState* execCallee, Instruction* pc,
         ASSERT(callType != CallTypeJS);
     
         if (callType == CallTypeHost) {
+            execCallee->setCallee(asObject(callee));
             globalData.hostCallReturnValue = JSValue::decode(callData.native.function(execCallee));
             
             LLINT_CALL_RETURN(execCallee, pc, reinterpret_cast<void*>(getHostCallReturnValue));
@@ -1262,6 +1263,7 @@ static SlowPathReturnType handleHostCall(ExecState* execCallee, Instruction* pc,
     ASSERT(constructType != ConstructTypeJS);
     
     if (constructType == ConstructTypeHost) {
+        execCallee->setCallee(asObject(callee));
         globalData.hostCallReturnValue = JSValue::decode(constructData.native.function(execCallee));
 
         LLINT_CALL_RETURN(execCallee, pc, reinterpret_cast<void*>(getHostCallReturnValue));
index 68a693a..aa0b91b 100644 (file)
@@ -993,7 +993,7 @@ PassRefPtr<ParsedNode> Parser<LexerType>::parse(JSGlobalObject* lexicalGlobalObj
         else if (isEvalNode<ParsedNode>())
             *exception = createSyntaxError(lexicalGlobalObject, errMsg);
         else
-            *exception = addErrorInfo(&lexicalGlobalObject->globalData(), createSyntaxError(lexicalGlobalObject, errMsg), errLine, *m_source, Vector<StackFrame>());
+            *exception = addErrorInfo(lexicalGlobalObject->globalExec(), createSyntaxError(lexicalGlobalObject, errMsg), errLine, *m_source);
     }
 
     if (debugger && !ParsedNode::scopeIsFunction)
index 5266c1e..87eb23b 100644 (file)
@@ -120,37 +120,21 @@ JSObject* createURIError(ExecState* exec, const UString& message)
     return createURIError(exec->lexicalGlobalObject(), message);
 }
 
-JSObject* addErrorInfo(JSGlobalData* globalData, JSObject* error, int line, const SourceCode& source, const Vector<StackFrame>& stackTrace)
+JSObject* addErrorInfo(CallFrame* callFrame, JSObject* error, int line, const SourceCode& source)
 {
+    JSGlobalData* globalData = &callFrame->globalData();
     const UString& sourceURL = source.provider()->url();
 
     if (line != -1)
         error->putDirect(*globalData, Identifier(globalData, linePropertyName), jsNumber(line), ReadOnly | DontDelete);
     if (!sourceURL.isNull())
         error->putDirect(*globalData, Identifier(globalData, sourceURLPropertyName), jsString(globalData, sourceURL), ReadOnly | DontDelete);
-    if (!stackTrace.isEmpty()) {
-        JSGlobalObject* globalObject = 0;
-        if (isTerminatedExecutionException(error) || isInterruptedExecutionException(error))
-            globalObject = globalData->dynamicGlobalObject;
-        else
-            globalObject = error->globalObject();
-        StringBuilder builder;
-        for (unsigned i = 0; i < stackTrace.size(); i++) {
-            builder.append(String(stackTrace[i].toString(globalObject->globalExec()).impl()));
-            if (i != stackTrace.size() - 1)
-                builder.append('\n');
-        }
-
-        error->putDirect(*globalData, globalData->propertyNames->stack, jsString(globalData, UString(builder.toString().impl())), ReadOnly | DontDelete);
-    }
+
+    globalData->interpreter->addStackTraceIfNecessary(callFrame, error);
 
     return error;
 }
 
-JSObject* addErrorInfo(ExecState* exec, JSObject* error, int line, const SourceCode& source, const Vector<StackFrame>& stackTrace)
-{
-    return addErrorInfo(&exec->globalData(), error, line, source, stackTrace);
-}
 
 bool hasErrorInfo(ExecState* exec, JSObject* error)
 {
@@ -160,12 +144,15 @@ bool hasErrorInfo(ExecState* exec, JSObject* error)
 
 JSValue throwError(ExecState* exec, JSValue error)
 {
+    if (error.isObject())
+        return throwError(exec, asObject(error));
     exec->globalData().exception = error;
     return error;
 }
 
 JSObject* throwError(ExecState* exec, JSObject* error)
 {
+    Interpreter::addStackTraceIfNecessary(exec, error);
     exec->globalData().exception = error;
     return error;
 }
index 59b3949..ad50542 100644 (file)
@@ -57,9 +57,8 @@ namespace JSC {
 
     // Methods to add 
     bool hasErrorInfo(ExecState*, JSObject* error);
-    JSObject* addErrorInfo(JSGlobalData*, JSObject* error, int line, const SourceCode&, const Vector<StackFrame>&);
     // ExecState wrappers.
-    JSObject* addErrorInfo(ExecState*, JSObject* error, int line, const SourceCode&, const Vector<StackFrame>&);
+    JSObject* addErrorInfo(ExecState*, JSObject* error, int line, const SourceCode&);
 
     // Methods to throw Errors.
     JS_EXPORT_PRIVATE JSValue throwError(ExecState*, JSValue);