Title: [195283] releases/WebKitGTK/webkit-2.10/Source/_javascript_Core
Revision
195283
Author
[email protected]
Date
2016-01-19 03:23:52 -0800 (Tue, 19 Jan 2016)

Log Message

Merge r189454 - StackOverflow stack unwinding should stop at native frames.
https://bugs.webkit.org/show_bug.cgi?id=148749

Reviewed by Michael Saboff.

In the present code, after ping-pong'ing back and forth between native and JS
code a few times, if we have a stack overflow on re-entry into the VM to run
JS code's whose stack frame would overflow the JS stack, the code will end up
unwinding past the native function that is making the call to re-enter the VM.
As a result, any clean up code (e.g. destructors for stack variables) in the
skipped native function frame (and its chain of native function callers) will
not be called.

This patch is based on the Michael Saboff's fix of this issue landed on the
jsc-tailcall branch: http://trac.webkit.org/changeset/188555

We now check for the case where there are no JS frames to unwind since the
last native frame, and treat the exception as an unhandled exception.  The
native function is responsible for further propagating the exception if needed.

Other supporting work:
1. Remove vm->vmEntryFrameForThrow.  It should always be the same as
   vm->topVMEntryFrame.
2. Change operationThrowStackOverflowError() to use the throwStackOverflowError()
   helper function instead of rolling its own.
3. Added a test that exercises this edge case.  The test should not hang or crash.

* API/tests/PingPongStackOverflowTest.cpp: Added.
(PingPongStackOverflowObject_hasInstance):
(testPingPongStackOverflow):
* API/tests/PingPongStackOverflowTest.h: Added.
* API/tests/testapi.c:
(main):
* _javascript_Core.xcodeproj/project.pbxproj:
* interpreter/CallFrame.h:
(JSC::ExecState::operator=):
(JSC::ExecState::callerFrame):
(JSC::ExecState::callerFrameOrVMEntryFrame):
(JSC::ExecState::argIndexForRegister):
(JSC::ExecState::callerFrameAndPC):
* interpreter/Interpreter.cpp:
(JSC::UnwindFunctor::UnwindFunctor):
(JSC::UnwindFunctor::operator()):
(JSC::Interpreter::unwind):
* interpreter/Interpreter.h:
(JSC::NativeCallFrameTracer::NativeCallFrameTracer):
(JSC::Interpreter::sampler):
* jit/CCallHelpers.h:
(JSC::CCallHelpers::jumpToExceptionHandler):
* jit/JITExceptions.cpp:
(JSC::genericUnwind):
* jit/JITExceptions.h:
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_catch):
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::emit_op_catch):
* jit/JITOperations.cpp:
* llint/LowLevelInterpreter32_64.asm:
* llint/LowLevelInterpreter64.asm:
* runtime/VM.h:
(JSC::VM::exceptionOffset):
(JSC::VM::callFrameForThrowOffset):
(JSC::VM::vmEntryFrameForThrowOffset): Deleted.
(JSC::VM::topVMEntryFrameOffset): Deleted.

Modified Paths

Added Paths

Diff

Added: releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/API/tests/PingPongStackOverflowTest.cpp (0 => 195283)


--- releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/API/tests/PingPongStackOverflowTest.cpp	                        (rev 0)
+++ releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/API/tests/PingPongStackOverflowTest.cpp	2016-01-19 11:23:52 UTC (rev 195283)
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "PingPongStackOverflowTest.h"
+
+#include "InitializeThreading.h"
+#include "JSContextRefPrivate.h"
+#include "_javascript_Core.h"
+#include "Options.h"
+#include <wtf/text/StringBuilder.h>
+
+using JSC::Options;
+
+static JSGlobalContextRef context = nullptr;
+static int nativeRecursionCount = 0;
+
+static bool PingPongStackOverflowObject_hasInstance(JSContextRef context, JSObjectRef constructor, JSValueRef possibleValue, JSValueRef* exception)
+{
+    UNUSED_PARAM(context);
+    UNUSED_PARAM(constructor);
+
+    JSStringRef hasInstanceName = JSStringCreateWithUTF8CString("hasInstance");
+    JSValueRef hasInstance = JSObjectGetProperty(context, constructor, hasInstanceName, exception);
+    JSStringRelease(hasInstanceName);
+    if (!hasInstance)
+        return false;
+
+    int countAtEntry = nativeRecursionCount++;
+
+    JSValueRef result = 0;
+    if (nativeRecursionCount < 100) {
+        JSObjectRef function = JSValueToObject(context, hasInstance, exception);
+        result = JSObjectCallAsFunction(context, function, constructor, 1, &possibleValue, exception);
+    } else {
+        StringBuilder builder;
+        builder.append("dummy.valueOf([0]");
+        for (int i = 1; i < 35000; i++) {
+            builder.append(", [");
+            builder.appendNumber(i);
+            builder.append("]");
+        }
+        builder.append(");");
+
+        JSStringRef script = JSStringCreateWithUTF8CString(builder.toString().utf8().data());
+        result = JSEvaluateScript(context, script, NULL, NULL, 1, exception);
+        JSStringRelease(script);
+    }
+
+    --nativeRecursionCount;
+    if (nativeRecursionCount != countAtEntry)
+        printf("    ERROR: PingPongStackOverflow test saw a recursion count mismatch\n");
+
+    return result && JSValueToBoolean(context, result);
+}
+
+JSClassDefinition PingPongStackOverflowObject_definition = {
+    0,
+    kJSClassAttributeNone,
+    
+    "PingPongStackOverflowObject",
+    NULL,
+    
+    NULL,
+    NULL,
+    
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    PingPongStackOverflowObject_hasInstance,
+    NULL,
+};
+
+static JSClassRef PingPongStackOverflowObject_class(JSContextRef context)
+{
+    UNUSED_PARAM(context);
+    
+    static JSClassRef jsClass;
+    if (!jsClass)
+        jsClass = JSClassCreate(&PingPongStackOverflowObject_definition);
+    
+    return jsClass;
+}
+
+// This tests tests a stack overflow on VM reentry into a JS function from a native function
+// after ping-pong'ing back and forth between JS and native functions multiple times.
+// This test should not hang or crash.
+int testPingPongStackOverflow()
+{
+    bool failed = false;
+
+    JSC::initializeThreading();
+    Options::initialize(); // Ensure options is initialized first.
+
+    auto origReservedZoneSize = Options::reservedZoneSize();
+    auto origErrorModeReservedZoneSize = Options::errorModeReservedZoneSize();
+    auto origUseLLInt = Options::useLLInt();
+    auto origMaxPerThreadStackUsage = Options::maxPerThreadStackUsage();
+
+    Options::reservedZoneSize() = 128 * KB;
+    Options::errorModeReservedZoneSize() = 64 * KB;
+#if ENABLE(JIT)
+    // Normally, we want to disable the LLINT to force the use of JITted code which is necessary for
+    // reproducing the regression in https://bugs.webkit.org/show_bug.cgi?id=148749. However, we only
+    // want to do this if the LLINT isn't the only available execution engine.
+    Options::useLLInt() = false;
+#endif
+
+    const char* scriptString =
+        "var count = 0;" \
+        "PingPongStackOverflowObject.hasInstance = function f() {" \
+        "    return (undefined instanceof PingPongStackOverflowObject);" \
+        "};" \
+        "PingPongStackOverflowObject.__proto__ = undefined;" \
+        "undefined instanceof PingPongStackOverflowObject;";
+
+    JSValueRef scriptResult = nullptr;
+    JSValueRef exception = nullptr;
+    JSStringRef script = JSStringCreateWithUTF8CString(scriptString);
+
+    nativeRecursionCount = 0;
+    context = JSGlobalContextCreateInGroup(nullptr, nullptr);
+
+    JSObjectRef globalObject = JSContextGetGlobalObject(context);
+    ASSERT(JSValueIsObject(context, globalObject));
+
+    JSObjectRef PingPongStackOverflowObject = JSObjectMake(context, PingPongStackOverflowObject_class(context), NULL);
+    JSStringRef PingPongStackOverflowObjectString = JSStringCreateWithUTF8CString("PingPongStackOverflowObject");
+    JSObjectSetProperty(context, globalObject, PingPongStackOverflowObjectString, PingPongStackOverflowObject, kJSPropertyAttributeNone, NULL);
+    JSStringRelease(PingPongStackOverflowObjectString);
+
+    unsigned stackSize = 32 * KB;
+    Options::maxPerThreadStackUsage() = stackSize + Options::reservedZoneSize();
+
+    exception = nullptr;
+    scriptResult = JSEvaluateScript(context, script, nullptr, nullptr, 1, &exception);
+
+    if (!exception) {
+        printf("FAIL: PingPongStackOverflowError not thrown in PingPongStackOverflow test\n");
+        failed = true;
+    } else if (nativeRecursionCount) {
+        printf("FAIL: Unbalanced native recursion count: %d in PingPongStackOverflow test\n", nativeRecursionCount);
+        failed = true;
+    } else {
+        printf("PASS: PingPongStackOverflow test.\n");
+    }
+
+    Options::reservedZoneSize() = origReservedZoneSize;
+    Options::errorModeReservedZoneSize() = origErrorModeReservedZoneSize;
+    Options::useLLInt() = origUseLLInt;
+    Options::maxPerThreadStackUsage() = origMaxPerThreadStackUsage;
+
+    return failed;
+}

Added: releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/API/tests/PingPongStackOverflowTest.h (0 => 195283)


--- releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/API/tests/PingPongStackOverflowTest.h	                        (rev 0)
+++ releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/API/tests/PingPongStackOverflowTest.h	2016-01-19 11:23:52 UTC (rev 195283)
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PingPongStackOverflowTest_h
+#define PingPongStackOverflowTest_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int testPingPongStackOverflow();
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* PingPongStackOverflowTest_h */

Modified: releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/API/tests/testapi.c (195282 => 195283)


--- releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/API/tests/testapi.c	2016-01-19 11:23:11 UTC (rev 195282)
+++ releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/API/tests/testapi.c	2016-01-19 11:23:52 UTC (rev 195283)
@@ -41,10 +41,10 @@
 
 #include "CompareAndSwapTest.h"
 #include "CustomGlobalObjectClassTest.h"
+#include "ExecutionTimeLimitTest.h"
 #include "GlobalContextWithFinalizerTest.h"
+#include "PingPongStackOverflowTest.h"
 
-#include "ExecutionTimeLimitTest.h"
-
 #if JSC_OBJC_API_ENABLED
 void testObjectiveCAPI(void);
 #endif
@@ -1893,6 +1893,7 @@
 
     failed = testExecutionTimeLimit() || failed;
     failed = testGlobalContextWithFinalizer() || failed;
+    failed = testPingPongStackOverflow() || failed;
 
     // Clear out local variables pointing at JSObjectRefs to allow their values to be collected
     function = NULL;

Modified: releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/ChangeLog (195282 => 195283)


--- releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/ChangeLog	2016-01-19 11:23:11 UTC (rev 195282)
+++ releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/ChangeLog	2016-01-19 11:23:52 UTC (rev 195283)
@@ -1,3 +1,70 @@
+2015-09-06  Mark Lam  <[email protected]>
+
+        StackOverflow stack unwinding should stop at native frames.
+        https://bugs.webkit.org/show_bug.cgi?id=148749
+
+        Reviewed by Michael Saboff.
+
+        In the present code, after ping-pong'ing back and forth between native and JS
+        code a few times, if we have a stack overflow on re-entry into the VM to run
+        JS code's whose stack frame would overflow the JS stack, the code will end up
+        unwinding past the native function that is making the call to re-enter the VM.
+        As a result, any clean up code (e.g. destructors for stack variables) in the
+        skipped native function frame (and its chain of native function callers) will
+        not be called.
+
+        This patch is based on the Michael Saboff's fix of this issue landed on the
+        jsc-tailcall branch: http://trac.webkit.org/changeset/188555
+
+        We now check for the case where there are no JS frames to unwind since the
+        last native frame, and treat the exception as an unhandled exception.  The
+        native function is responsible for further propagating the exception if needed.
+
+        Other supporting work:
+        1. Remove vm->vmEntryFrameForThrow.  It should always be the same as
+           vm->topVMEntryFrame.
+        2. Change operationThrowStackOverflowError() to use the throwStackOverflowError()
+           helper function instead of rolling its own.
+        3. Added a test that exercises this edge case.  The test should not hang or crash.
+
+        * API/tests/PingPongStackOverflowTest.cpp: Added.
+        (PingPongStackOverflowObject_hasInstance):
+        (testPingPongStackOverflow):
+        * API/tests/PingPongStackOverflowTest.h: Added.
+        * API/tests/testapi.c:
+        (main):
+        * _javascript_Core.xcodeproj/project.pbxproj:
+        * interpreter/CallFrame.h:
+        (JSC::ExecState::operator=):
+        (JSC::ExecState::callerFrame):
+        (JSC::ExecState::callerFrameOrVMEntryFrame):
+        (JSC::ExecState::argIndexForRegister):
+        (JSC::ExecState::callerFrameAndPC):
+        * interpreter/Interpreter.cpp:
+        (JSC::UnwindFunctor::UnwindFunctor):
+        (JSC::UnwindFunctor::operator()):
+        (JSC::Interpreter::unwind):
+        * interpreter/Interpreter.h:
+        (JSC::NativeCallFrameTracer::NativeCallFrameTracer):
+        (JSC::Interpreter::sampler):
+        * jit/CCallHelpers.h:
+        (JSC::CCallHelpers::jumpToExceptionHandler):
+        * jit/JITExceptions.cpp:
+        (JSC::genericUnwind):
+        * jit/JITExceptions.h:
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::emit_op_catch):
+        * jit/JITOpcodes32_64.cpp:
+        (JSC::JIT::emit_op_catch):
+        * jit/JITOperations.cpp:
+        * llint/LowLevelInterpreter32_64.asm:
+        * llint/LowLevelInterpreter64.asm:
+        * runtime/VM.h:
+        (JSC::VM::exceptionOffset):
+        (JSC::VM::callFrameForThrowOffset):
+        (JSC::VM::vmEntryFrameForThrowOffset): Deleted.
+        (JSC::VM::topVMEntryFrameOffset): Deleted.
+
 2016-01-15  Konstantin Tokarev  <[email protected]>
 
         [mips] Implemented emitFunctionPrologue/Epilogue

Modified: releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (195282 => 195283)


--- releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2016-01-19 11:23:11 UTC (rev 195282)
+++ releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2016-01-19 11:23:52 UTC (rev 195283)
@@ -1725,6 +1725,7 @@
 		FE5932A8183C5A2600A1ECCC /* VMEntryScope.h in Headers */ = {isa = PBXBuildFile; fileRef = FE5932A6183C5A2600A1ECCC /* VMEntryScope.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		FE7BA60F1A1A7CEC00F1F7B4 /* HeapVerifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE7BA60D1A1A7CEC00F1F7B4 /* HeapVerifier.cpp */; };
 		FE7BA6101A1A7CEC00F1F7B4 /* HeapVerifier.h in Headers */ = {isa = PBXBuildFile; fileRef = FE7BA60E1A1A7CEC00F1F7B4 /* HeapVerifier.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		FE7C41961B97FC4B00F4D598 /* PingPongStackOverflowTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FEDA50D41B97F442009A3B4F /* PingPongStackOverflowTest.cpp */; };
 		FEA08620182B7A0400F6D851 /* Breakpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = FEA0861E182B7A0400F6D851 /* Breakpoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		FEA08621182B7A0400F6D851 /* DebuggerPrimitives.h in Headers */ = {isa = PBXBuildFile; fileRef = FEA0861F182B7A0400F6D851 /* DebuggerPrimitives.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		FEB51F6C1A97B688001F921C /* Regress141809.mm in Sources */ = {isa = PBXBuildFile; fileRef = FEB51F6B1A97B688001F921C /* Regress141809.mm */; };
@@ -3597,6 +3598,8 @@
 		FED287B115EC9A5700DA8161 /* LLIntOpcode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntOpcode.h; path = llint/LLIntOpcode.h; sourceTree = "<group>"; };
 		FED94F2B171E3E2300BE77A4 /* Watchdog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Watchdog.cpp; sourceTree = "<group>"; };
 		FED94F2C171E3E2300BE77A4 /* Watchdog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Watchdog.h; sourceTree = "<group>"; };
+		FEDA50D41B97F442009A3B4F /* PingPongStackOverflowTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PingPongStackOverflowTest.cpp; path = API/tests/PingPongStackOverflowTest.cpp; sourceTree = "<group>"; };
+		FEDA50D51B97F4D9009A3B4F /* PingPongStackOverflowTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PingPongStackOverflowTest.h; path = API/tests/PingPongStackOverflowTest.h; sourceTree = "<group>"; };
 		FEF040501AAE662D00BD28B0 /* CompareAndSwapTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CompareAndSwapTest.cpp; path = API/tests/CompareAndSwapTest.cpp; sourceTree = "<group>"; };
 		FEF040521AAEC4ED00BD28B0 /* CompareAndSwapTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CompareAndSwapTest.h; path = API/tests/CompareAndSwapTest.h; sourceTree = "<group>"; };
 		FEF6835A174343CC00A32E25 /* JITStubsARM.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITStubsARM.h; sourceTree = "<group>"; };
@@ -3970,6 +3973,8 @@
 				FE0D4A081ABA2437002F54BF /* GlobalContextWithFinalizerTest.h */,
 				C2181FC018A948FB0025A235 /* JSExportTests.h */,
 				C2181FC118A948FB0025A235 /* JSExportTests.mm */,
+				FEDA50D41B97F442009A3B4F /* PingPongStackOverflowTest.cpp */,
+				FEDA50D51B97F4D9009A3B4F /* PingPongStackOverflowTest.h */,
 				65570F581AA4C00A009B3C23 /* Regress141275.h */,
 				65570F591AA4C00A009B3C23 /* Regress141275.mm */,
 				FEB51F6A1A97B688001F921C /* Regress141809.h */,
@@ -7203,6 +7208,7 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				FE7C41961B97FC4B00F4D598 /* PingPongStackOverflowTest.cpp in Sources */,
 				FE0D4A091ABA2437002F54BF /* GlobalContextWithFinalizerTest.cpp in Sources */,
 				65570F5A1AA4C3EA009B3C23 /* Regress141275.mm in Sources */,
 				C29ECB031804D0ED00D2CBB4 /* CurrentThisInsideBlockGetterTest.mm in Sources */,

Modified: releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/interpreter/CallFrame.h (195282 => 195283)


--- releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/interpreter/CallFrame.h	2016-01-19 11:23:11 UTC (rev 195282)
+++ releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/interpreter/CallFrame.h	2016-01-19 11:23:52 UTC (rev 195283)
@@ -96,6 +96,7 @@
         CallFrame& operator=(const Register& r) { *static_cast<Register*>(this) = r; return *this; }
 
         CallFrame* callerFrame() const { return static_cast<CallFrame*>(callerFrameOrVMEntryFrame()); }
+        void* callerFrameOrVMEntryFrame() const { return callerFrameAndPC().callerFrame; }
 
         JS_EXPORT_PRIVATE CallFrame* callerFrame(VMEntryFrame*&);
 
@@ -307,8 +308,6 @@
             return argIndex;
         }
 
-        void* callerFrameOrVMEntryFrame() const { return callerFrameAndPC().callerFrame; }
-
         CallerFrameAndPC& callerFrameAndPC() { return *reinterpret_cast<CallerFrameAndPC*>(this); }
         const CallerFrameAndPC& callerFrameAndPC() const { return *reinterpret_cast<const CallerFrameAndPC*>(this); }
 

Modified: releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/interpreter/Interpreter.cpp (195282 => 195283)


--- releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/interpreter/Interpreter.cpp	2016-01-19 11:23:11 UTC (rev 195282)
+++ releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/interpreter/Interpreter.cpp	2016-01-19 11:23:52 UTC (rev 195283)
@@ -618,9 +618,8 @@
 
 class UnwindFunctor {
 public:
-    UnwindFunctor(VMEntryFrame*& vmEntryFrame, CallFrame*& callFrame, bool isTermination, CodeBlock*& codeBlock, HandlerInfo*& handler)
-        : m_vmEntryFrame(vmEntryFrame)
-        , m_callFrame(callFrame)
+    UnwindFunctor(CallFrame*& callFrame, bool isTermination, CodeBlock*& codeBlock, HandlerInfo*& handler)
+        : m_callFrame(callFrame)
         , m_isTermination(isTermination)
         , m_codeBlock(codeBlock)
         , m_handler(handler)
@@ -630,7 +629,6 @@
     StackVisitor::Status operator()(StackVisitor& visitor)
     {
         VM& vm = m_callFrame->vm();
-        m_vmEntryFrame = visitor->vmEntryFrame();
         m_callFrame = visitor->callFrame();
         m_codeBlock = visitor->codeBlock();
         unsigned bytecodeOffset = visitor->bytecodeOffset();
@@ -648,15 +646,22 @@
     }
 
 private:
-    VMEntryFrame*& m_vmEntryFrame;
     CallFrame*& m_callFrame;
     bool m_isTermination;
     CodeBlock*& m_codeBlock;
     HandlerInfo*& m_handler;
 };
 
-NEVER_INLINE HandlerInfo* Interpreter::unwind(VMEntryFrame*& vmEntryFrame, CallFrame*& callFrame, Exception* exception)
+NEVER_INLINE HandlerInfo* Interpreter::unwind(VM& vm, CallFrame*& callFrame, Exception* exception, UnwindStart unwindStart)
 {
+    if (unwindStart == UnwindFromCallerFrame) {
+        if (callFrame->callerFrameOrVMEntryFrame() == vm.topVMEntryFrame)
+            return nullptr;
+
+        callFrame = callFrame->callerFrame();
+        vm.topCallFrame = callFrame;
+    }
+
     CodeBlock* codeBlock = callFrame->codeBlock();
     bool isTermination = false;
 
@@ -671,13 +676,13 @@
     if (exceptionValue.isObject())
         isTermination = isTerminatedExecutionException(exception);
 
-    ASSERT(callFrame->vm().exception() && callFrame->vm().exception()->stack().size());
+    ASSERT(vm.exception() && vm.exception()->stack().size());
 
     Debugger* debugger = callFrame->vmEntryGlobalObject()->debugger();
     if (debugger && debugger->needsExceptionCallbacks() && !exception->didNotifyInspectorOfThrow()) {
         // We need to clear the exception here in order to see if a new exception happens.
         // Afterwards, the values are put back to continue processing this error.
-        SuspendExceptionScope scope(&callFrame->vm());
+        SuspendExceptionScope scope(&vm);
         // This code assumes that if the debugger is enabled then there is no inlining.
         // If that assumption turns out to be false then we'll ignore the inlined call
         // frames.
@@ -700,13 +705,11 @@
     exception->setDidNotifyInspectorOfThrow();
 
     // Calculate an exception handler vPC, unwinding call frames as necessary.
-    HandlerInfo* handler = 0;
-    VM& vm = callFrame->vm();
-    ASSERT(callFrame == vm.topCallFrame);
-    UnwindFunctor functor(vmEntryFrame, callFrame, isTermination, codeBlock, handler);
+    HandlerInfo* handler = nullptr;
+    UnwindFunctor functor(callFrame, isTermination, codeBlock, handler);
     callFrame->iterate(functor);
     if (!handler)
-        return 0;
+        return nullptr;
 
     if (LegacyProfiler* profiler = vm.enabledProfiler())
         profiler->exceptionUnwind(callFrame);

Modified: releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/interpreter/Interpreter.h (195282 => 195283)


--- releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/interpreter/Interpreter.h	2016-01-19 11:23:11 UTC (rev 195282)
+++ releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/interpreter/Interpreter.h	2016-01-19 11:23:52 UTC (rev 195283)
@@ -62,6 +62,8 @@
     struct Instruction;
     struct ProtoCallFrame;
 
+    enum UnwindStart { UnwindFromCurrentFrame, UnwindFromCallerFrame };
+
     enum DebugHookID {
         WillExecuteProgram,
         DidExecuteProgram,
@@ -139,6 +141,7 @@
         {
             ASSERT(vm);
             ASSERT(callFrame);
+            ASSERT(callFrame < vm->topVMEntryFrame);
             vm->topCallFrame = callFrame;
         }
     };
@@ -215,7 +218,7 @@
         
         SamplingTool* sampler() { return m_sampler.get(); }
 
-        NEVER_INLINE HandlerInfo* unwind(VMEntryFrame*&, CallFrame*&, Exception*);
+        NEVER_INLINE HandlerInfo* unwind(VM&, CallFrame*&, Exception*, UnwindStart);
         NEVER_INLINE void debug(CallFrame*, DebugHookID);
         JSString* stackTraceAsString(ExecState*, Vector<StackFrame>);
 

Modified: releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/jit/CCallHelpers.h (195282 => 195283)


--- releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/jit/CCallHelpers.h	2016-01-19 11:23:11 UTC (rev 195282)
+++ releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/jit/CCallHelpers.h	2016-01-19 11:23:52 UTC (rev 195283)
@@ -2060,7 +2060,6 @@
     void jumpToExceptionHandler()
     {
         // genericUnwind() leaves the handler CallFrame* in vm->callFrameForThrow,
-        // the topVMEntryFrame for the handler in vm->vmEntryFrameForThrow,
         // and the address of the handler in vm->targetMachinePCForThrow.
         loadPtr(&vm()->targetMachinePCForThrow, GPRInfo::regT1);
         jump(GPRInfo::regT1);

Modified: releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/jit/JITExceptions.cpp (195282 => 195283)


--- releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/jit/JITExceptions.cpp	2016-01-19 11:23:11 UTC (rev 195282)
+++ releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/jit/JITExceptions.cpp	2016-01-19 11:23:52 UTC (rev 195283)
@@ -40,7 +40,7 @@
 
 namespace JSC {
 
-void genericUnwind(VM* vm, ExecState* callFrame)
+void genericUnwind(VM* vm, ExecState* callFrame, UnwindStart unwindStart)
 {
     if (Options::breakOnThrow()) {
         dataLog("In call frame ", RawPointer(callFrame), " for code block ", *callFrame->codeBlock(), "\n");
@@ -49,8 +49,7 @@
     
     Exception* exception = vm->exception();
     RELEASE_ASSERT(exception);
-    VMEntryFrame* vmEntryFrame = vm->topVMEntryFrame;
-    HandlerInfo* handler = vm->interpreter->unwind(vmEntryFrame, callFrame, exception); // This may update vmEntryFrame and callFrame.
+    HandlerInfo* handler = vm->interpreter->unwind(*vm, callFrame, exception, unwindStart); // This may update callFrame.
 
     void* catchRoutine;
     Instruction* catchPCForInterpreter = 0;
@@ -64,7 +63,6 @@
     } else
         catchRoutine = LLInt::getCodePtr(handleUncaughtException);
     
-    vm->vmEntryFrameForThrow = vmEntryFrame;
     vm->callFrameForThrow = callFrame;
     vm->targetMachinePCForThrow = catchRoutine;
     vm->targetInterpreterPCForThrow = catchPCForInterpreter;

Modified: releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/jit/JITExceptions.h (195282 => 195283)


--- releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/jit/JITExceptions.h	2016-01-19 11:23:11 UTC (rev 195282)
+++ releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/jit/JITExceptions.h	2016-01-19 11:23:52 UTC (rev 195283)
@@ -26,6 +26,7 @@
 #ifndef JITExceptions_h
 #define JITExceptions_h
 
+#include "Interpreter.h"
 #include "JSCJSValue.h"
 
 namespace JSC {
@@ -33,7 +34,7 @@
 class ExecState;
 class VM;
 
-void genericUnwind(VM*, ExecState*);
+void genericUnwind(VM*, ExecState*, UnwindStart = UnwindFromCurrentFrame);
 
 } // namespace JSC
 

Modified: releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/jit/JITOpcodes.cpp (195282 => 195283)


--- releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/jit/JITOpcodes.cpp	2016-01-19 11:23:11 UTC (rev 195282)
+++ releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/jit/JITOpcodes.cpp	2016-01-19 11:23:52 UTC (rev 195283)
@@ -501,8 +501,6 @@
     
     move(TrustedImmPtr(m_vm), regT3);
     load64(Address(regT3, VM::callFrameForThrowOffset()), callFrameRegister);
-    load64(Address(regT3, VM::vmEntryFrameForThrowOffset()), regT0);
-    store64(regT0, Address(regT3, VM::topVMEntryFrameOffset()));
 
     addPtr(TrustedImm32(stackPointerOffsetFor(codeBlock()) * sizeof(Register)), callFrameRegister, stackPointerRegister);
 

Modified: releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/jit/JITOpcodes32_64.cpp (195282 => 195283)


--- releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/jit/JITOpcodes32_64.cpp	2016-01-19 11:23:11 UTC (rev 195282)
+++ releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/jit/JITOpcodes32_64.cpp	2016-01-19 11:23:52 UTC (rev 195283)
@@ -803,8 +803,6 @@
     move(TrustedImmPtr(m_vm), regT3);
     // operationThrow returns the callFrame for the handler.
     load32(Address(regT3, VM::callFrameForThrowOffset()), callFrameRegister);
-    load32(Address(regT3, VM::vmEntryFrameForThrowOffset()), regT0);
-    store32(regT0, Address(regT3, VM::topVMEntryFrameOffset()));
 
     addPtr(TrustedImm32(stackPointerOffsetFor(codeBlock()) * sizeof(Register)), callFrameRegister, stackPointerRegister);
 

Modified: releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/jit/JITOperations.cpp (195282 => 195283)


--- releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/jit/JITOperations.cpp	2016-01-19 11:23:11 UTC (rev 195282)
+++ releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/jit/JITOperations.cpp	2016-01-19 11:23:52 UTC (rev 195283)
@@ -91,20 +91,18 @@
         callerFrame = exec;
 
     NativeCallFrameTracerWithRestore tracer(vm, vmEntryFrame, callerFrame);
-    ErrorHandlingScope errorScope(*vm);
-    vm->throwException(callerFrame, createStackOverflowError(callerFrame));
+    throwStackOverflowError(callerFrame);
 }
 
 int32_t JIT_OPERATION operationCallArityCheck(ExecState* exec)
 {
     VM* vm = &exec->vm();
-    VMEntryFrame* vmEntryFrame = vm->topVMEntryFrame;
-    CallFrame* callerFrame = exec->callerFrame(vmEntryFrame);
-
     JSStack& stack = vm->interpreter->stack();
 
     int32_t missingArgCount = CommonSlowPaths::arityCheckFor(exec, &stack, CodeForCall);
     if (missingArgCount < 0) {
+        VMEntryFrame* vmEntryFrame = vm->topVMEntryFrame;
+        CallFrame* callerFrame = exec->callerFrame(vmEntryFrame);
         NativeCallFrameTracerWithRestore tracer(vm, vmEntryFrame, callerFrame);
         throwStackOverflowError(callerFrame);
     }
@@ -115,13 +113,12 @@
 int32_t JIT_OPERATION operationConstructArityCheck(ExecState* exec)
 {
     VM* vm = &exec->vm();
-    VMEntryFrame* vmEntryFrame = vm->topVMEntryFrame;
-    CallFrame* callerFrame = exec->callerFrame(vmEntryFrame);
-
     JSStack& stack = vm->interpreter->stack();
 
     int32_t missingArgCount = CommonSlowPaths::arityCheckFor(exec, &stack, CodeForConstruct);
     if (missingArgCount < 0) {
+        VMEntryFrame* vmEntryFrame = vm->topVMEntryFrame;
+        CallFrame* callerFrame = exec->callerFrame(vmEntryFrame);
         NativeCallFrameTracerWithRestore tracer(vm, vmEntryFrame, callerFrame);
         throwStackOverflowError(callerFrame);
     }
@@ -1830,7 +1827,7 @@
     JSValue exceptionValue = JSValue::decode(encodedExceptionValue);
     vm->throwException(exec, exceptionValue);
 
-    // Results stored out-of-band in vm.targetMachinePCForThrow, vm.callFrameForThrow & vm.vmEntryFrameForThrow
+    // Results stored out-of-band in vm.targetMachinePCForThrow & vm.callFrameForThrow
     genericUnwind(vm, exec);
 }
 
@@ -1876,12 +1873,8 @@
 
 void JIT_OPERATION lookupExceptionHandlerFromCallerFrame(VM* vm, ExecState* exec)
 {
-    VMEntryFrame* vmEntryFrame = vm->topVMEntryFrame;
-    CallFrame* callerFrame = exec->callerFrame(vmEntryFrame);
-    ASSERT(callerFrame);
-
-    NativeCallFrameTracerWithRestore tracer(vm, vmEntryFrame, callerFrame);
-    genericUnwind(vm, callerFrame);
+    NativeCallFrameTracer tracer(vm, exec);
+    genericUnwind(vm, exec, UnwindFromCallerFrame);
     ASSERT(vm->targetMachinePCForThrow);
 }
 

Modified: releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm (195282 => 195283)


--- releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm	2016-01-19 11:23:11 UTC (rev 195282)
+++ releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm	2016-01-19 11:23:52 UTC (rev 195283)
@@ -1931,8 +1931,6 @@
     andp MarkedBlockMask, t3
     loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
     loadp VM::callFrameForThrow[t3], cfr
-    loadp VM::vmEntryFrameForThrow[t3], t0
-    storep t0, VM::topVMEntryFrame[t3]
     restoreStackPointerAfterCall()
 
     loadi VM::targetInterpreterPCForThrow[t3], PC

Modified: releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/llint/LowLevelInterpreter64.asm (195282 => 195283)


--- releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/llint/LowLevelInterpreter64.asm	2016-01-19 11:23:11 UTC (rev 195282)
+++ releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/llint/LowLevelInterpreter64.asm	2016-01-19 11:23:52 UTC (rev 195283)
@@ -1795,8 +1795,6 @@
     andp MarkedBlockMask, t3
     loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
     loadp VM::callFrameForThrow[t3], cfr
-    loadp VM::vmEntryFrameForThrow[t3], t0
-    storep t0, VM::topVMEntryFrame[t3]
     restoreStackPointerAfterCall()
 
     loadp CodeBlock[cfr], PB

Modified: releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/runtime/VM.h (195282 => 195283)


--- releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/runtime/VM.h	2016-01-19 11:23:11 UTC (rev 195282)
+++ releases/WebKitGTK/webkit-2.10/Source/_javascript_Core/runtime/VM.h	2016-01-19 11:23:52 UTC (rev 195283)
@@ -369,16 +369,6 @@
         return OBJECT_OFFSETOF(VM, m_exception);
     }
 
-    static ptrdiff_t vmEntryFrameForThrowOffset()
-    {
-        return OBJECT_OFFSETOF(VM, vmEntryFrameForThrow);
-    }
-
-    static ptrdiff_t topVMEntryFrameOffset()
-    {
-        return OBJECT_OFFSETOF(VM, topVMEntryFrame);
-    }
-
     static ptrdiff_t callFrameForThrowOffset()
     {
         return OBJECT_OFFSETOF(VM, callFrameForThrow);
@@ -451,7 +441,6 @@
     JSValue hostCallReturnValue;
     unsigned varargsLength;
     ExecState* newCallFrameReturnValue;
-    VMEntryFrame* vmEntryFrameForThrow;
     ExecState* callFrameForThrow;
     void* targetMachinePCForThrow;
     Instruction* targetInterpreterPCForThrow;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to