Diff
Modified: trunk/LayoutTests/ChangeLog (118955 => 118956)
--- trunk/LayoutTests/ChangeLog 2012-05-30 19:44:22 UTC (rev 118955)
+++ trunk/LayoutTests/ChangeLog 2012-05-30 19:45:20 UTC (rev 118956)
@@ -1,3 +1,22 @@
+2012-05-30 Oliver Hunt <[email protected]>
+
+ DFG does not correctly handle exceptions caught in the LLInt
+ https://bugs.webkit.org/show_bug.cgi?id=87885
+
+ Reviewed by Filip Pizlo.
+
+ Pile of code to convince the DFG to throw an exception that ends up being caught
+ in the LLInt
+
+ * fast/js/exception-propagate-from-dfg-to-llint-expected.txt: Added.
+ * fast/js/exception-propagate-from-dfg-to-llint.html: Added.
+ * fast/js/script-tests/exception-propagate-from-dfg-to-llint.js: Added.
+ (o.toString):
+ (h):
+ (g):
+ (f1):
+ (f2):
+
2012-05-30 Ulan Degenbaev <[email protected]>
[v8] Crash after redefining setter on typed array to a number
Added: trunk/LayoutTests/fast/js/exception-propagate-from-dfg-to-llint-expected.txt (0 => 118956)
--- trunk/LayoutTests/fast/js/exception-propagate-from-dfg-to-llint-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/js/exception-propagate-from-dfg-to-llint-expected.txt 2012-05-30 19:45:20 UTC (rev 118956)
@@ -0,0 +1,10 @@
+Ensures that we pass exceptions to the correct codeblock when throwing from the DFG to the LLInt.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Caught exception in correct codeblock
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/fast/js/exception-propagate-from-dfg-to-llint.html (0 => 118956)
--- trunk/LayoutTests/fast/js/exception-propagate-from-dfg-to-llint.html (rev 0)
+++ trunk/LayoutTests/fast/js/exception-propagate-from-dfg-to-llint.html 2012-05-30 19:45:20 UTC (rev 118956)
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/fast/js/script-tests/exception-propagate-from-dfg-to-llint.js (0 => 118956)
--- trunk/LayoutTests/fast/js/script-tests/exception-propagate-from-dfg-to-llint.js (rev 0)
+++ trunk/LayoutTests/fast/js/script-tests/exception-propagate-from-dfg-to-llint.js 2012-05-30 19:45:20 UTC (rev 118956)
@@ -0,0 +1,187 @@
+description("Ensures that we pass exceptions to the correct codeblock when throwing from the DFG to the LLInt.");
+var o = {
+ toString: function() { if (shouldThrow) throw {}; return ""; }
+};
+
+var shouldThrow = false;
+function h(o) {
+ return String(o);
+}
+
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+try { shouldThrow = !shouldThrow; h(o); } catch (e) {}
+
+
+function g() {
+ with({})
+ h(o);
+}
+
+function f1() {
+ try {
+ g();
+ } catch (e) {
+ testFailed("Caught exception in wrong codeblock");
+ }
+}
+
+function f2() {
+ try {
+ g();
+ } catch (e) {
+ testPassed("Caught exception in correct codeblock");
+ }
+}
+
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+f1();
+shouldThrow = true;
+f2();
+var successfullyParsed = true;
Modified: trunk/Source/_javascript_Core/ChangeLog (118955 => 118956)
--- trunk/Source/_javascript_Core/ChangeLog 2012-05-30 19:44:22 UTC (rev 118955)
+++ trunk/Source/_javascript_Core/ChangeLog 2012-05-30 19:45:20 UTC (rev 118956)
@@ -1,3 +1,17 @@
+2012-05-30 Oliver Hunt <[email protected]>
+
+ DFG does not correctly handle exceptions caught in the LLInt
+ https://bugs.webkit.org/show_bug.cgi?id=87885
+
+ Reviewed by Filip Pizlo.
+
+ Make the DFG use genericThrow, rather than reimplementing a small portion of it.
+ Also make the LLInt slow paths validate that their PC is correct.
+
+ * dfg/DFGOperations.cpp:
+ * llint/LLIntSlowPaths.cpp:
+ (LLInt):
+
2012-05-29 Filip Pizlo <[email protected]>
DFG CFA should infer types and values of captured variables
Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (118955 => 118956)
--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2012-05-30 19:44:22 UTC (rev 118955)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2012-05-30 19:45:20 UTC (rev 118956)
@@ -34,6 +34,7 @@
#include "GetterSetter.h"
#include <wtf/InlineASM.h>
#include "Interpreter.h"
+#include "JITExceptions.h"
#include "JSActivation.h"
#include "JSGlobalData.h"
#include "JSStaticScopeObject.h"
@@ -1149,35 +1150,31 @@
{
JSGlobalData* globalData = &exec->globalData();
NativeCallFrameTracer tracer(globalData, exec);
-
+
JSValue exceptionValue = exec->exception();
ASSERT(exceptionValue);
-
+
unsigned vPCIndex = exec->codeBlock()->bytecodeOffsetForCallAtIndex(callIndex);
- HandlerInfo* handler = exec->globalData().interpreter->throwException(exec, exceptionValue, vPCIndex);
-
- void* catchRoutine = handler ? handler->nativeCode.executableAddress() : (void*)ctiOpThrowNotCaught;
- ASSERT(catchRoutine);
- return dfgHandlerEncoded(exec, catchRoutine);
+ ExceptionHandler handler = genericThrow(globalData, exec, exceptionValue, vPCIndex);
+ ASSERT(handler.catchRoutine);
+ return dfgHandlerEncoded(handler.callFrame, handler.catchRoutine);
}
DFGHandlerEncoded DFG_OPERATION lookupExceptionHandlerInStub(ExecState* exec, StructureStubInfo* stubInfo)
{
JSGlobalData* globalData = &exec->globalData();
NativeCallFrameTracer tracer(globalData, exec);
-
+
JSValue exceptionValue = exec->exception();
ASSERT(exceptionValue);
CodeOrigin codeOrigin = stubInfo->codeOrigin;
while (codeOrigin.inlineCallFrame)
codeOrigin = codeOrigin.inlineCallFrame->caller;
-
- HandlerInfo* handler = exec->globalData().interpreter->throwException(exec, exceptionValue, codeOrigin.bytecodeIndex);
-
- void* catchRoutine = handler ? handler->nativeCode.executableAddress() : (void*)ctiOpThrowNotCaught;
- ASSERT(catchRoutine);
- return dfgHandlerEncoded(exec, catchRoutine);
+
+ ExceptionHandler handler = genericThrow(globalData, exec, exceptionValue, codeOrigin.bytecodeIndex);
+ ASSERT(handler.catchRoutine);
+ return dfgHandlerEncoded(handler.callFrame, handler.catchRoutine);
}
double DFG_OPERATION dfgConvertJSValueToNumber(ExecState* exec, EncodedJSValue value)
Modified: trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp (118955 => 118956)
--- trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp 2012-05-30 19:44:22 UTC (rev 118955)
+++ trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp 2012-05-30 19:45:20 UTC (rev 118956)
@@ -53,8 +53,16 @@
JSGlobalData& globalData = exec->globalData(); \
NativeCallFrameTracer tracer(&globalData, exec)
-#define LLINT_SET_PC_FOR_STUBS() \
- exec->setCurrentVPC(pc + 1)
+#ifndef NDEBUG
+#define LLINT_SET_PC_FOR_STUBS() do { \
+ exec->codeBlock()->bytecodeOffset(pc); \
+ exec->setCurrentVPC(pc + 1); \
+ } while (false)
+#else
+#define LLINT_SET_PC_FOR_STUBS() do { \
+ exec->setCurrentVPC(pc + 1); \
+ } while (false)
+#endif
#define LLINT_BEGIN() \
LLINT_BEGIN_NO_SET_PC(); \