Title: [190787] branches/safari-601.1.46-branch/Source/_javascript_Core
Revision
190787
Author
[email protected]
Date
2015-10-09 07:21:20 -0700 (Fri, 09 Oct 2015)

Log Message

Merge r189454. rdar://problem/22823239

Modified Paths

Added Paths

Diff

Added: branches/safari-601.1.46-branch/Source/_javascript_Core/API/tests/PingPongStackOverflowTest.cpp (0 => 190787)


--- branches/safari-601.1.46-branch/Source/_javascript_Core/API/tests/PingPongStackOverflowTest.cpp	                        (rev 0)
+++ branches/safari-601.1.46-branch/Source/_javascript_Core/API/tests/PingPongStackOverflowTest.cpp	2015-10-09 14:21:20 UTC (rev 190787)
@@ -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: branches/safari-601.1.46-branch/Source/_javascript_Core/API/tests/PingPongStackOverflowTest.h (0 => 190787)


--- branches/safari-601.1.46-branch/Source/_javascript_Core/API/tests/PingPongStackOverflowTest.h	                        (rev 0)
+++ branches/safari-601.1.46-branch/Source/_javascript_Core/API/tests/PingPongStackOverflowTest.h	2015-10-09 14:21:20 UTC (rev 190787)
@@ -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: branches/safari-601.1.46-branch/Source/_javascript_Core/API/tests/testapi.c (190786 => 190787)


--- branches/safari-601.1.46-branch/Source/_javascript_Core/API/tests/testapi.c	2015-10-09 14:21:10 UTC (rev 190786)
+++ branches/safari-601.1.46-branch/Source/_javascript_Core/API/tests/testapi.c	2015-10-09 14:21:20 UTC (rev 190787)
@@ -47,6 +47,8 @@
 #include "ExecutionTimeLimitTest.h"
 #endif
 
+#include "PingPongStackOverflowTest.h"
+
 #if JSC_OBJC_API_ENABLED
 void testObjectiveCAPI(void);
 #endif
@@ -111,9 +113,9 @@
     size_t jsLength = JSStringGetLength(valueAsString);
     const JSChar* jsBuffer = JSStringGetCharactersPtr(valueAsString);
 
-    CFStringRef expectedValueAsCFString = CFStringCreateWithCString(kCFAllocatorDefault, 
+    CFStringRef expectedValueAsCFString = CFStringCreateWithCString(kCFAllocatorDefault,
                                                                     expectedValue,
-                                                                    kCFStringEncodingUTF8);    
+                                                                    kCFStringEncodingUTF8);
     CFIndex cfLength = CFStringGetLength(expectedValueAsCFString);
     UniChar* cfBuffer = (UniChar*)malloc(cfLength * sizeof(UniChar));
     CFStringGetCharacters(expectedValueAsCFString, CFRangeMake(0, cfLength), cfBuffer);
@@ -123,7 +125,7 @@
         fprintf(stderr, "assertEqualsAsCharactersPtr failed: jsBuffer != cfBuffer\n");
         failed = 1;
     }
-    
+
     if (jsLength != (size_t)cfLength) {
 #if OS(WINDOWS)
         fprintf(stderr, "assertEqualsAsCharactersPtr failed: jsLength(%Iu) != cfLength(%Iu)\n", jsLength, (size_t)cfLength);
@@ -164,7 +166,7 @@
         || JSStringIsEqualToUTF8CString(propertyName, "0")) {
         return true;
     }
-    
+
     return false;
 }
 
@@ -172,11 +174,11 @@
 {
     UNUSED_PARAM(context);
     UNUSED_PARAM(object);
-    
+
     if (JSStringIsEqualToUTF8CString(propertyName, "alwaysOne")) {
         return JSValueMakeNumber(context, 1);
     }
-    
+
     if (JSStringIsEqualToUTF8CString(propertyName, "myPropertyName")) {
         return JSValueMakeNumber(context, 1);
     }
@@ -184,7 +186,7 @@
     if (JSStringIsEqualToUTF8CString(propertyName, "cantFind")) {
         return JSValueMakeUndefined(context);
     }
-    
+
     if (JSStringIsEqualToUTF8CString(propertyName, "hasPropertyLie")) {
         return 0;
     }
@@ -197,7 +199,7 @@
         *exception = JSValueMakeNumber(context, 1);
         return JSValueMakeNumber(context, 1);
     }
-    
+
     return JSValueMakeNull(context);
 }
 
@@ -210,11 +212,11 @@
 
     if (JSStringIsEqualToUTF8CString(propertyName, "cantSet"))
         return true; // pretend we set the property in order to swallow it
-    
+
     if (JSStringIsEqualToUTF8CString(propertyName, "throwOnSet")) {
         JSEvaluateScript(context, JSStringCreateWithUTF8CString("throw 'an exception'"), object, JSStringCreateWithUTF8CString("test script"), 1, exception);
     }
-    
+
     return false;
 }
 
@@ -222,10 +224,10 @@
 {
     UNUSED_PARAM(context);
     UNUSED_PARAM(object);
-    
+
     if (JSStringIsEqualToUTF8CString(propertyName, "cantDelete"))
         return true;
-    
+
     if (JSStringIsEqualToUTF8CString(propertyName, "throwOnDelete")) {
         JSEvaluateScript(context, JSStringCreateWithUTF8CString("throw 'an exception'"), object, JSStringCreateWithUTF8CString("test script"), 1, exception);
         return false;
@@ -238,13 +240,13 @@
 {
     UNUSED_PARAM(context);
     UNUSED_PARAM(object);
-    
+
     JSStringRef propertyName;
-    
+
     propertyName = JSStringCreateWithUTF8CString("alwaysOne");
     JSPropertyNameAccumulatorAddName(propertyNames, propertyName);
     JSStringRelease(propertyName);
-    
+
     propertyName = JSStringCreateWithUTF8CString("myPropertyName");
     JSPropertyNameAccumulatorAddName(propertyNames, propertyName);
     JSStringRelease(propertyName);
@@ -264,7 +266,7 @@
 
     if (argumentCount > 0 && JSValueIsStrictEqual(context, arguments[0], JSValueMakeNumber(context, 0)))
         return JSValueMakeNumber(context, 1);
-    
+
     return JSValueMakeUndefined(context);
 }
 
@@ -280,7 +282,7 @@
 
     if (argumentCount > 0 && JSValueIsStrictEqual(context, arguments[0], JSValueMakeNumber(context, 0)))
         return JSValueToObject(context, JSValueMakeNumber(context, 1), exception);
-    
+
     return JSValueToObject(context, JSValueMakeNumber(context, 0), exception);
 }
 
@@ -305,7 +307,7 @@
 {
     UNUSED_PARAM(object);
     UNUSED_PARAM(exception);
-    
+
     switch (type) {
     case kJSTypeNumber:
         return JSValueMakeNumber(context, 1);
@@ -358,13 +360,13 @@
 JSClassDefinition MyObject_definition = {
     0,
     kJSClassAttributeNone,
-    
+
     "MyObject",
     NULL,
-    
+
     evilStaticValues,
     evilStaticFunctions,
-    
+
     NULL,
     NULL,
     MyObject_hasProperty,
@@ -381,13 +383,13 @@
 JSClassDefinition MyObject_convertToTypeWrapperDefinition = {
     0,
     kJSClassAttributeNone,
-    
+
     "MyObject",
     NULL,
-    
+
     NULL,
     NULL,
-    
+
     NULL,
     NULL,
     NULL,
@@ -404,13 +406,13 @@
 JSClassDefinition MyObject_nullWrapperDefinition = {
     0,
     kJSClassAttributeNone,
-    
+
     "MyObject",
     NULL,
-    
+
     NULL,
     NULL,
-    
+
     NULL,
     NULL,
     NULL,
@@ -464,7 +466,7 @@
         // Swallow all .y gets after 5, returning null.
         return JSValueMakeNull(context);
     }
-    
+
     if (JSStringIsEqualToUTF8CString(propertyName, "z")) {
         static size_t count;
         if (count++ < 5)
@@ -509,7 +511,7 @@
 
     static size_t count;
     static const char* numbers[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
-    
+
     // Provide a property of a different name every time.
     JSStringRef propertyName = JSStringCreateWithUTF8CString(numbers[count++ % 10]);
     JSPropertyNameAccumulatorAddName(propertyNames, propertyName);
@@ -519,13 +521,13 @@
 JSClassDefinition PropertyCatchalls_definition = {
     0,
     kJSClassAttributeNone,
-    
+
     "PropertyCatchalls",
     NULL,
-    
+
     NULL,
     NULL,
-    
+
     NULL,
     NULL,
     NULL,
@@ -546,7 +548,7 @@
     static JSClassRef jsClass;
     if (!jsClass)
         jsClass = JSClassCreate(&PropertyCatchalls_definition);
-    
+
     return jsClass;
 }
 
@@ -554,7 +556,7 @@
 {
     UNUSED_PARAM(context);
     UNUSED_PARAM(constructor);
-    
+
     JSStringRef hasInstanceName = JSStringCreateWithUTF8CString("hasInstance");
     JSValueRef hasInstance = JSObjectGetProperty(context, constructor, hasInstanceName, exception);
     JSStringRelease(hasInstanceName);
@@ -580,15 +582,15 @@
     default:
         return JSValueMakeNull(context);
     }
-    
+
     JSValueRef func = JSObjectGetProperty(context, object, funcName, exception);
-    JSStringRelease(funcName);    
+    JSStringRelease(funcName);
     JSObjectRef function = JSValueToObject(context, func, exception);
     if (!function)
         return JSValueMakeNull(context);
     JSValueRef value = JSObjectCallAsFunction(context, function, object, 0, NULL, exception);
     if (!value) {
-        JSStringRef errorString = JSStringCreateWithUTF8CString("convertToType failed"); 
+        JSStringRef errorString = JSStringCreateWithUTF8CString("convertToType failed");
         JSValueRef errorStringRef = JSValueMakeString(context, errorString);
         JSStringRelease(errorString);
         return errorStringRef;
@@ -622,24 +624,24 @@
 static JSClassRef EvilExceptionObject_class(JSContextRef context)
 {
     UNUSED_PARAM(context);
-    
+
     static JSClassRef jsClass;
     if (!jsClass)
         jsClass = JSClassCreate(&EvilExceptionObject_definition);
-    
+
     return jsClass;
 }
 
 JSClassDefinition EmptyObject_definition = {
     0,
     kJSClassAttributeNone,
-    
+
     NULL,
     NULL,
-    
+
     NULL,
     NULL,
-    
+
     NULL,
     NULL,
     NULL,
@@ -656,11 +658,11 @@
 static JSClassRef EmptyObject_class(JSContextRef context)
 {
     UNUSED_PARAM(context);
-    
+
     static JSClassRef jsClass;
     if (!jsClass)
         jsClass = JSClassCreate(&EmptyObject_definition);
-    
+
     return jsClass;
 }
 
@@ -691,7 +693,7 @@
     UNUSED_PARAM(argumentCount);
     UNUSED_PARAM(arguments);
     UNUSED_PARAM(exception);
-    
+
     return JSValueMakeNumber(ctx, 1); // distinguish base call from derived call
 }
 
@@ -703,7 +705,7 @@
     UNUSED_PARAM(argumentCount);
     UNUSED_PARAM(arguments);
     UNUSED_PARAM(exception);
-    
+
     return 0; // should convert to undefined!
 }
 
@@ -784,7 +786,7 @@
     UNUSED_PARAM(argumentCount);
     UNUSED_PARAM(arguments);
     UNUSED_PARAM(exception);
-    
+
     return JSValueMakeNumber(ctx, 2); // distinguish base call from derived call
 }
 
@@ -853,7 +855,7 @@
     UNUSED_PARAM(exception);
 
     ASSERT(JSContextGetGlobalContext(ctx) == context);
-    
+
     if (argumentCount > 0) {
         JSStringRef string = JSValueToStringCopy(ctx, arguments[0], NULL);
         size_t sizeUTF8 = JSStringGetMaximumUTF8CStringSize(string);
@@ -863,7 +865,7 @@
         free(stringUTF8);
         JSStringRelease(string);
     }
-    
+
     return JSValueMakeUndefined(ctx);
 }
 
@@ -871,14 +873,14 @@
 {
     UNUSED_PARAM(constructorObject);
     UNUSED_PARAM(exception);
-    
+
     JSObjectRef result = JSObjectMake(context, NULL, NULL);
     if (argumentCount > 0) {
         JSStringRef value = JSStringCreateWithUTF8CString("value");
         JSObjectSetProperty(context, result, value, arguments[0], kJSPropertyAttributeNone, NULL);
         JSStringRelease(value);
     }
-    
+
     return result;
 }
 
@@ -889,7 +891,7 @@
     UNUSED_PARAM(argumentCount);
     UNUSED_PARAM(arguments);
     UNUSED_PARAM(exception);
-    
+
     return 0;
 }
 
@@ -1046,7 +1048,7 @@
     UNUSED_PARAM(arguments);
     JSValueRef jsUndefined = JSValueMakeUndefined(JSContextGetGlobalContext(ctx));
     JSValueToObject(JSContextGetGlobalContext(ctx), jsUndefined, exception);
-    
+
     return JSValueMakeUndefined(ctx);
 }
 static bool valueToObjectExceptionTest()
@@ -1068,11 +1070,11 @@
 
     JSStringRef test = JSStringCreateWithUTF8CString("valueToObject();");
     JSEvaluateScript(testContext, test, NULL, NULL, 1, NULL);
-    
+
     JSStringRelease(test);
     JSClassRelease(globalObjectClass);
     JSGlobalContextRelease(testContext);
-    
+
     return true;
 }
 
@@ -1144,7 +1146,7 @@
     if (argc > 1) {
         scriptPath = argv[1];
     }
-    
+
     // Test garbage collection with a fresh context
     context = JSGlobalContextCreateInGroup(NULL, NULL);
     TestInitializeFinalize = true;
@@ -1163,18 +1165,18 @@
     context = JSGlobalContextCreateInGroup(NULL, globalObjectClass);
 
     JSContextGroupRef contextGroup = JSContextGetGroup(context);
-    
+
     JSGlobalContextRetain(context);
     JSGlobalContextRelease(context);
     ASSERT(JSContextGetGlobalContext(context) == context);
-    
+
     JSReportExtraMemoryCost(context, 0);
     JSReportExtraMemoryCost(context, 1);
     JSReportExtraMemoryCost(context, 1024);
 
     JSObjectRef globalObject = JSContextGetGlobalObject(context);
     ASSERT(JSValueIsObject(context, globalObject));
-    
+
     JSValueRef jsUndefined = JSValueMakeUndefined(context);
     JSValueRef jsNull = JSValueMakeNull(context);
     JSValueRef jsTrue = JSValueMakeBoolean(context, true);
@@ -1195,12 +1197,12 @@
     // FIXME: test funny utf8 characters
     JSStringRef jsEmptyIString = JSStringCreateWithUTF8CString("");
     JSValueRef jsEmptyString = JSValueMakeString(context, jsEmptyIString);
-    
+
     JSStringRef jsOneIString = JSStringCreateWithUTF8CString("1");
     JSValueRef jsOneString = JSValueMakeString(context, jsOneIString);
 
     UniChar singleUniChar = 65; // Capital A
-    CFMutableStringRef cfString = 
+    CFMutableStringRef cfString =
         CFStringCreateMutableWithExternalCharactersNoCopy(kCFAllocatorDefault,
                                                           &singleUniChar,
                                                           1,
@@ -1209,20 +1211,20 @@
 
     JSStringRef jsCFIString = JSStringCreateWithCFString(cfString);
     JSValueRef jsCFString = JSValueMakeString(context, jsCFIString);
-    
+
     CFStringRef cfEmptyString = CFStringCreateWithCString(kCFAllocatorDefault, "", kCFStringEncodingUTF8);
-    
+
     JSStringRef jsCFEmptyIString = JSStringCreateWithCFString(cfEmptyString);
     JSValueRef jsCFEmptyString = JSValueMakeString(context, jsCFEmptyIString);
 
     CFIndex cfStringLength = CFStringGetLength(cfString);
     UniChar* buffer = (UniChar*)malloc(cfStringLength * sizeof(UniChar));
-    CFStringGetCharacters(cfString, 
-                          CFRangeMake(0, cfStringLength), 
+    CFStringGetCharacters(cfString,
+                          CFRangeMake(0, cfStringLength),
                           buffer);
     JSStringRef jsCFIStringWithCharacters = JSStringCreateWithCharacters((JSChar*)buffer, cfStringLength);
     JSValueRef jsCFStringWithCharacters = JSValueMakeString(context, jsCFIStringWithCharacters);
-    
+
     JSStringRef jsCFEmptyIStringWithCharacters = JSStringCreateWithCharacters((JSChar*)buffer, CFStringGetLength(cfEmptyString));
     free(buffer);
     JSValueRef jsCFEmptyStringWithCharacters = JSValueMakeString(context, jsCFEmptyIStringWithCharacters);
@@ -1301,17 +1303,17 @@
     JSStringRef myObjectIString = JSStringCreateWithUTF8CString("MyObject");
     JSObjectSetProperty(context, globalObject, myObjectIString, myObject, kJSPropertyAttributeNone, NULL);
     JSStringRelease(myObjectIString);
-    
+
     JSObjectRef EvilExceptionObject = JSObjectMake(context, EvilExceptionObject_class(context), NULL);
     JSStringRef EvilExceptionObjectIString = JSStringCreateWithUTF8CString("EvilExceptionObject");
     JSObjectSetProperty(context, globalObject, EvilExceptionObjectIString, EvilExceptionObject, kJSPropertyAttributeNone, NULL);
     JSStringRelease(EvilExceptionObjectIString);
-    
+
     JSObjectRef EmptyObject = JSObjectMake(context, EmptyObject_class(context), NULL);
     JSStringRef EmptyObjectIString = JSStringCreateWithUTF8CString("EmptyObject");
     JSObjectSetProperty(context, globalObject, EmptyObjectIString, EmptyObject, kJSPropertyAttributeNone, NULL);
     JSStringRelease(EmptyObjectIString);
-    
+
     JSStringRef lengthStr = JSStringCreateWithUTF8CString("length");
     JSObjectRef aStackRef = JSObjectMakeArray(context, 0, 0, 0);
     aHeapRef = aStackRef;
@@ -1415,7 +1417,7 @@
     str = JSStringCreateWithUTF8CString("({get a(){ throw '';}})");
     JSValueRef unstringifiableObj = JSEvaluateScript(context, str, NULL, NULL, 1, NULL);
     JSStringRelease(str);
-    
+
     str = JSValueCreateJSONString(context, unstringifiableObj, 4, 0);
     if (str) {
         printf("FAIL: Didn't return null when attempting to serialize unserializable value.\n");
@@ -1423,7 +1425,7 @@
         failed = 1;
     } else
         printf("PASS: returned null when attempting to serialize unserializable value.\n");
-    
+
     str = JSValueCreateJSONString(context, unstringifiableObj, 4, &exception);
     if (str) {
         printf("FAIL: Didn't return null when attempting to serialize unserializable value.\n");
@@ -1440,7 +1442,7 @@
     exception = NULL;
     ASSERT(NULL == JSValueToObject(context, jsNull, &exception));
     ASSERT(exception);
-    
+
     exception = NULL;
     // FIXME <rdar://4668451> - On i386 the isnan(double) macro tries to map to the isnan(float) function,
     // causing a build break with -Wshorten-64-to-32 enabled.  The issue is known by the appropriate team.
@@ -1451,13 +1453,13 @@
     exception = NULL;
     ASSERT(!JSValueToStringCopy(context, jsObjectNoProto, &exception));
     ASSERT(exception);
-    
+
     ASSERT(JSValueToBoolean(context, myObject));
-    
+
     exception = NULL;
     ASSERT(!JSValueIsEqual(context, jsObjectNoProto, JSValueMakeNumber(context, 1), &exception));
     ASSERT(exception);
-    
+
     exception = NULL;
     JSObjectGetPropertyAtIndex(context, myObject, 0, &exception);
     ASSERT(1 == JSValueToNumber(context, exception, NULL));
@@ -1475,7 +1477,7 @@
     assertEqualsAsBoolean(jsCFStringWithCharacters, true);
     assertEqualsAsBoolean(jsCFEmptyString, false);
     assertEqualsAsBoolean(jsCFEmptyStringWithCharacters, false);
-    
+
     assertEqualsAsNumber(jsUndefined, nan(""));
     assertEqualsAsNumber(jsNull, 0);
     assertEqualsAsNumber(jsTrue, 1);
@@ -1490,7 +1492,7 @@
     assertEqualsAsNumber(jsCFEmptyString, 0);
     assertEqualsAsNumber(jsCFEmptyStringWithCharacters, 0);
     ASSERT(sizeof(JSChar) == sizeof(UniChar));
-    
+
     assertEqualsAsCharactersPtr(jsUndefined, "undefined");
     assertEqualsAsCharactersPtr(jsNull, "null");
     assertEqualsAsCharactersPtr(jsTrue, "true");
@@ -1504,7 +1506,7 @@
     assertEqualsAsCharactersPtr(jsCFStringWithCharacters, "A");
     assertEqualsAsCharactersPtr(jsCFEmptyString, "");
     assertEqualsAsCharactersPtr(jsCFEmptyStringWithCharacters, "");
-    
+
     assertEqualsAsUTF8String(jsUndefined, "undefined");
     assertEqualsAsUTF8String(jsNull, "null");
     assertEqualsAsUTF8String(jsTrue, "true");
@@ -1518,15 +1520,15 @@
     assertEqualsAsUTF8String(jsCFStringWithCharacters, "A");
     assertEqualsAsUTF8String(jsCFEmptyString, "");
     assertEqualsAsUTF8String(jsCFEmptyStringWithCharacters, "");
-    
+
     checkConstnessInJSObjectNames();
-    
+
     ASSERT(JSValueIsStrictEqual(context, jsTrue, jsTrue));
     ASSERT(!JSValueIsStrictEqual(context, jsOne, jsOneString));
 
     ASSERT(JSValueIsEqual(context, jsOne, jsOneString, NULL));
     ASSERT(!JSValueIsEqual(context, jsTrue, jsFalse, NULL));
-    
+
     CFStringRef cfJSString = JSStringCopyCFString(kCFAllocatorDefault, jsCFIString);
     CFStringRef cfJSEmptyString = JSStringCopyCFString(kCFAllocatorDefault, jsCFEmptyIString);
     ASSERT(CFEqual(cfJSString, cfString));
@@ -1536,7 +1538,7 @@
 
     CFRelease(cfString);
     CFRelease(cfEmptyString);
-    
+
     jsGlobalValue = JSObjectMake(context, NULL, NULL);
     makeGlobalNumberValue(context);
     JSValueProtect(context, jsGlobalValue);
@@ -1566,7 +1568,7 @@
     result = JSEvaluateScript(context, badSyntax, NULL, NULL, 1, &exception);
     ASSERT(!result);
     ASSERT(JSValueIsObject(context, exception));
-    
+
     JSStringRef array = JSStringCreateWithUTF8CString("Array");
     JSObjectRef arrayConstructor = JSValueToObject(context, JSObjectGetProperty(context, globalObject, array, NULL), NULL);
     JSStringRelease(array);
@@ -1580,17 +1582,17 @@
     exception = NULL;
     ASSERT(JSValueIsUndefined(context, JSObjectGetPropertyAtIndex(context, o, 0, &exception)));
     ASSERT(!exception);
-    
+
     JSObjectSetPropertyAtIndex(context, o, 0, JSValueMakeNumber(context, 1), &exception);
     ASSERT(!exception);
-    
+
     exception = NULL;
     ASSERT(1 == JSValueToNumber(context, JSObjectGetPropertyAtIndex(context, o, 0, &exception), &exception));
     ASSERT(!exception);
 
     JSStringRef functionBody;
     JSObjectRef function;
-    
+
     exception = NULL;
     functionBody = JSStringCreateWithUTF8CString("rreturn Array;");
     JSStringRef line = JSStringCreateWithUTF8CString("line");
@@ -1630,14 +1632,14 @@
     v = JSObjectCallAsFunction(context, function, NULL, 0, NULL, NULL);
     ASSERT(v);
     ASSERT(JSValueIsEqual(context, v, arrayConstructor, NULL));
-    
+
     exception = NULL;
     function = JSObjectMakeFunction(context, NULL, 0, NULL, jsEmptyIString, NULL, 0, &exception);
     ASSERT(!exception);
     v = JSObjectCallAsFunction(context, function, NULL, 0, NULL, &exception);
     ASSERT(v && !exception);
     ASSERT(JSValueIsUndefined(context, v));
-    
+
     exception = NULL;
     v = NULL;
     JSStringRef foo = JSStringCreateWithUTF8CString("foo");
@@ -1649,16 +1651,16 @@
     JSObjectCallAsFunction(context, function, NULL, 1, arguments, &exception);
     JSStringRelease(foo);
     JSStringRelease(functionBody);
-    
+
     string = JSValueToStringCopy(context, function, NULL);
     assertEqualsAsUTF8String(JSValueMakeString(context, string), "function foo(foo) {\nreturn foo;\n}");
     JSStringRelease(string);
 
     JSStringRef print = JSStringCreateWithUTF8CString("print");
     JSObjectRef printFunction = JSObjectMakeFunctionWithCallback(context, print, print_callAsFunction);
-    JSObjectSetProperty(context, globalObject, print, printFunction, kJSPropertyAttributeNone, NULL); 
+    JSObjectSetProperty(context, globalObject, print, printFunction, kJSPropertyAttributeNone, NULL);
     JSStringRelease(print);
-    
+
     ASSERT(!JSObjectSetPrivate(printFunction, (void*)1));
     ASSERT(!JSObjectGetPrivate(printFunction));
 
@@ -1666,25 +1668,25 @@
     JSObjectRef myConstructor = JSObjectMakeConstructor(context, NULL, myConstructor_callAsConstructor);
     JSObjectSetProperty(context, globalObject, myConstructorIString, myConstructor, kJSPropertyAttributeNone, NULL);
     JSStringRelease(myConstructorIString);
-    
+
     JSStringRef myBadConstructorIString = JSStringCreateWithUTF8CString("MyBadConstructor");
     JSObjectRef myBadConstructor = JSObjectMakeConstructor(context, NULL, myBadConstructor_callAsConstructor);
     JSObjectSetProperty(context, globalObject, myBadConstructorIString, myBadConstructor, kJSPropertyAttributeNone, NULL);
     JSStringRelease(myBadConstructorIString);
-    
+
     ASSERT(!JSObjectSetPrivate(myConstructor, (void*)1));
     ASSERT(!JSObjectGetPrivate(myConstructor));
-    
+
     string = JSStringCreateWithUTF8CString("Base");
     JSObjectRef baseConstructor = JSObjectMakeConstructor(context, Base_class(context), NULL);
     JSObjectSetProperty(context, globalObject, string, baseConstructor, kJSPropertyAttributeNone, NULL);
     JSStringRelease(string);
-    
+
     string = JSStringCreateWithUTF8CString("Derived");
     JSObjectRef derivedConstructor = JSObjectMakeConstructor(context, Derived_class(context), NULL);
     JSObjectSetProperty(context, globalObject, string, derivedConstructor, kJSPropertyAttributeNone, NULL);
     JSStringRelease(string);
-    
+
     string = JSStringCreateWithUTF8CString("Derived2");
     JSObjectRef derived2Constructor = JSObjectMakeConstructor(context, Derived2_class(context), NULL);
     JSObjectSetProperty(context, globalObject, string, derived2Constructor, kJSPropertyAttributeNone, NULL);
@@ -1739,7 +1741,7 @@
     nullDefinition.attributes = kJSClassAttributeNoAutomaticPrototype;
     JSClassRef nullClass = JSClassCreate(&nullDefinition);
     JSClassRelease(nullClass);
-    
+
     nullDefinition = kJSClassDefinitionEmpty;
     nullClass = JSClassCreate(&nullDefinition);
     JSClassRelease(nullClass);
@@ -1875,6 +1877,7 @@
     failed = testExecutionTimeLimit() || failed;
 #endif /* OS(DARWIN) */
     failed = testGlobalContextWithFinalizer() || failed;
+    failed = testPingPongStackOverflow() || failed;
 
     // Clear out local variables pointing at JSObjectRefs to allow their values to be collected
     function = NULL;
@@ -1939,18 +1942,18 @@
 static char* createStringWithContentsOfFile(const char* fileName)
 {
     char* buffer;
-    
+
     size_t buffer_size = 0;
     size_t buffer_capacity = 1024;
     buffer = (char*)malloc(buffer_capacity);
-    
+
     FILE* f = fopen(fileName, "r");
     if (!f) {
         fprintf(stderr, "Could not open file: %s\n", fileName);
         free(buffer);
         return 0;
     }
-    
+
     while (!feof(f) && !ferror(f)) {
         buffer_size += fread(buffer + buffer_size, 1, buffer_capacity - buffer_size, f);
         if (buffer_size == buffer_capacity) { // guarantees space for trailing '\0'
@@ -1958,12 +1961,12 @@
             buffer = (char*)realloc(buffer, buffer_capacity);
             ASSERT(buffer);
         }
-        
+
         ASSERT(buffer_size < buffer_capacity);
     }
     fclose(f);
     buffer[buffer_size] = '\0';
-    
+
     return buffer;
 }
 

Modified: branches/safari-601.1.46-branch/Source/_javascript_Core/ChangeLog (190786 => 190787)


--- branches/safari-601.1.46-branch/Source/_javascript_Core/ChangeLog	2015-10-09 14:21:10 UTC (rev 190786)
+++ branches/safari-601.1.46-branch/Source/_javascript_Core/ChangeLog	2015-10-09 14:21:20 UTC (rev 190787)
@@ -1,3 +1,74 @@
+2015-10-08  Matthew Hanson  <[email protected]>
+
+        Merge r189454. rdar://problem/22823239
+
+    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.
+
 2015-09-03  Babak Shafiei  <[email protected]>
 
         Merge r189046.

Modified: branches/safari-601.1.46-branch/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (190786 => 190787)


--- branches/safari-601.1.46-branch/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2015-10-09 14:21:10 UTC (rev 190786)
+++ branches/safari-601.1.46-branch/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2015-10-09 14:21:20 UTC (rev 190787)
@@ -1677,6 +1677,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 */; };
@@ -3492,6 +3493,8 @@
 		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>"; };
 		FED94F2D171E3E2300BE77A4 /* WatchdogMac.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WatchdogMac.cpp; 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>"; };
@@ -3864,6 +3867,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 */,
@@ -7003,6 +7008,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: branches/safari-601.1.46-branch/Source/_javascript_Core/interpreter/CallFrame.h (190786 => 190787)


--- branches/safari-601.1.46-branch/Source/_javascript_Core/interpreter/CallFrame.h	2015-10-09 14:21:10 UTC (rev 190786)
+++ branches/safari-601.1.46-branch/Source/_javascript_Core/interpreter/CallFrame.h	2015-10-09 14:21:20 UTC (rev 190787)
@@ -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*&);
 
@@ -303,8 +304,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: branches/safari-601.1.46-branch/Source/_javascript_Core/interpreter/Interpreter.cpp (190786 => 190787)


--- branches/safari-601.1.46-branch/Source/_javascript_Core/interpreter/Interpreter.cpp	2015-10-09 14:21:10 UTC (rev 190786)
+++ branches/safari-601.1.46-branch/Source/_javascript_Core/interpreter/Interpreter.cpp	2015-10-09 14:21:20 UTC (rev 190787)
@@ -613,9 +613,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)
@@ -625,7 +624,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();
@@ -643,15 +641,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;
 
@@ -666,13 +671,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.
@@ -695,13 +700,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: branches/safari-601.1.46-branch/Source/_javascript_Core/interpreter/Interpreter.h (190786 => 190787)


--- branches/safari-601.1.46-branch/Source/_javascript_Core/interpreter/Interpreter.h	2015-10-09 14:21:10 UTC (rev 190786)
+++ branches/safari-601.1.46-branch/Source/_javascript_Core/interpreter/Interpreter.h	2015-10-09 14:21:20 UTC (rev 190787)
@@ -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: branches/safari-601.1.46-branch/Source/_javascript_Core/jit/CCallHelpers.h (190786 => 190787)


--- branches/safari-601.1.46-branch/Source/_javascript_Core/jit/CCallHelpers.h	2015-10-09 14:21:10 UTC (rev 190786)
+++ branches/safari-601.1.46-branch/Source/_javascript_Core/jit/CCallHelpers.h	2015-10-09 14:21:20 UTC (rev 190787)
@@ -2015,7 +2015,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: branches/safari-601.1.46-branch/Source/_javascript_Core/jit/JITExceptions.cpp (190786 => 190787)


--- branches/safari-601.1.46-branch/Source/_javascript_Core/jit/JITExceptions.cpp	2015-10-09 14:21:10 UTC (rev 190786)
+++ branches/safari-601.1.46-branch/Source/_javascript_Core/jit/JITExceptions.cpp	2015-10-09 14:21:20 UTC (rev 190787)
@@ -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: branches/safari-601.1.46-branch/Source/_javascript_Core/jit/JITExceptions.h (190786 => 190787)


--- branches/safari-601.1.46-branch/Source/_javascript_Core/jit/JITExceptions.h	2015-10-09 14:21:10 UTC (rev 190786)
+++ branches/safari-601.1.46-branch/Source/_javascript_Core/jit/JITExceptions.h	2015-10-09 14:21:20 UTC (rev 190787)
@@ -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: branches/safari-601.1.46-branch/Source/_javascript_Core/jit/JITOpcodes.cpp (190786 => 190787)


--- branches/safari-601.1.46-branch/Source/_javascript_Core/jit/JITOpcodes.cpp	2015-10-09 14:21:10 UTC (rev 190786)
+++ branches/safari-601.1.46-branch/Source/_javascript_Core/jit/JITOpcodes.cpp	2015-10-09 14:21:20 UTC (rev 190787)
@@ -522,8 +522,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: branches/safari-601.1.46-branch/Source/_javascript_Core/jit/JITOpcodes32_64.cpp (190786 => 190787)


--- branches/safari-601.1.46-branch/Source/_javascript_Core/jit/JITOpcodes32_64.cpp	2015-10-09 14:21:10 UTC (rev 190786)
+++ branches/safari-601.1.46-branch/Source/_javascript_Core/jit/JITOpcodes32_64.cpp	2015-10-09 14:21:20 UTC (rev 190787)
@@ -824,8 +824,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: branches/safari-601.1.46-branch/Source/_javascript_Core/jit/JITOperations.cpp (190786 => 190787)


--- branches/safari-601.1.46-branch/Source/_javascript_Core/jit/JITOperations.cpp	2015-10-09 14:21:10 UTC (rev 190786)
+++ branches/safari-601.1.46-branch/Source/_javascript_Core/jit/JITOperations.cpp	2015-10-09 14:21:20 UTC (rev 190787)
@@ -111,20 +111,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);
     }
@@ -135,13 +133,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);
     }
@@ -1917,7 +1914,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);
 }
 
@@ -1963,12 +1960,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: branches/safari-601.1.46-branch/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm (190786 => 190787)


--- branches/safari-601.1.46-branch/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm	2015-10-09 14:21:10 UTC (rev 190786)
+++ branches/safari-601.1.46-branch/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm	2015-10-09 14:21:20 UTC (rev 190787)
@@ -1947,8 +1947,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: branches/safari-601.1.46-branch/Source/_javascript_Core/llint/LowLevelInterpreter64.asm (190786 => 190787)


--- branches/safari-601.1.46-branch/Source/_javascript_Core/llint/LowLevelInterpreter64.asm	2015-10-09 14:21:10 UTC (rev 190786)
+++ branches/safari-601.1.46-branch/Source/_javascript_Core/llint/LowLevelInterpreter64.asm	2015-10-09 14:21:20 UTC (rev 190787)
@@ -1811,8 +1811,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: branches/safari-601.1.46-branch/Source/_javascript_Core/runtime/VM.h (190786 => 190787)


--- branches/safari-601.1.46-branch/Source/_javascript_Core/runtime/VM.h	2015-10-09 14:21:10 UTC (rev 190786)
+++ branches/safari-601.1.46-branch/Source/_javascript_Core/runtime/VM.h	2015-10-09 14:21:20 UTC (rev 190787)
@@ -352,16 +352,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);
@@ -426,7 +416,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