Title: [160947] branches/jsCStack/Source/_javascript_Core
Revision
160947
Author
mark....@apple.com
Date
2013-12-20 16:56:24 -0800 (Fri, 20 Dec 2013)

Log Message

CStack: callToJavaScript should do stack check for incoming args.
https://bugs.webkit.org/show_bug.cgi?id=126088.

Not yet reviewed.

1. Change callToJavaScript()'s prototype to:
       EncodedJSValue callToJavaScript(void*, VM*, ProtoCallFrame*);

   We now pass VM* instead of &vm.topCallFrame for the second argument.
   This gives us greater utility out of that arg.
   We also now save the VM* in the VMEntrySentinelFrame instead of
   &vm.topCallFrame.

2. Change callToJavaScript() to do a stack check to ensure that we have
   adequate stack space to copy all the args from the protoCallFrame.
   If not, it'll throw a StackOverflowError.

3. Removed JSStack::entryCheck() and calls to it.

   callToJavaScript now takes care of the stack check that ensures
   adequate stack space for incoming args.
   callToJavaScript does assume that we have adequate stack space for
   the VMEntrySentinelFrame, but that is ensured by our stack host zone.

Changes to callToJavaScript are done in the doCallToJavaScript macro.
Hence, all the changes apply to callToNativeFunction as well.

* interpreter/Interpreter.cpp:
(JSC::Interpreter::execute):
(JSC::Interpreter::executeCall):
(JSC::Interpreter::executeConstruct):
(JSC::Interpreter::prepareForRepeatCall):
* interpreter/JSStack.h:
* interpreter/JSStackInlines.h:
* jit/JITCode.cpp:
(JSC::JITCode::execute):
* jit/JITStubs.h:
* jit/JITStubsMSVC64.asm: Added a FIXME.
* jit/JITStubsX86.h: Added a FIXME.
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::llint_throw_stack_overflow_error):
* llint/LLIntSlowPaths.h:
* llint/LLIntThunks.h:
* llint/LowLevelInterpreter64.asm:

Modified Paths

Diff

Modified: branches/jsCStack/Source/_javascript_Core/ChangeLog (160946 => 160947)


--- branches/jsCStack/Source/_javascript_Core/ChangeLog	2013-12-21 00:44:36 UTC (rev 160946)
+++ branches/jsCStack/Source/_javascript_Core/ChangeLog	2013-12-21 00:56:24 UTC (rev 160947)
@@ -1,3 +1,50 @@
+2013-12-20  Mark Lam  <mark....@apple.com>
+
+        CStack: callToJavaScript should do stack check for incoming args.
+        https://bugs.webkit.org/show_bug.cgi?id=126088.
+
+        Not yet reviewed.
+
+        1. Change callToJavaScript()'s prototype to:
+               EncodedJSValue callToJavaScript(void*, VM*, ProtoCallFrame*);
+
+           We now pass VM* instead of &vm.topCallFrame for the second argument.
+           This gives us greater utility out of that arg.
+           We also now save the VM* in the VMEntrySentinelFrame instead of
+           &vm.topCallFrame.
+
+        2. Change callToJavaScript() to do a stack check to ensure that we have
+           adequate stack space to copy all the args from the protoCallFrame.
+           If not, it'll throw a StackOverflowError.
+
+        3. Removed JSStack::entryCheck() and calls to it.
+
+           callToJavaScript now takes care of the stack check that ensures
+           adequate stack space for incoming args.
+           callToJavaScript does assume that we have adequate stack space for
+           the VMEntrySentinelFrame, but that is ensured by our stack host zone.
+
+        Changes to callToJavaScript are done in the doCallToJavaScript macro.
+        Hence, all the changes apply to callToNativeFunction as well.
+
+        * interpreter/Interpreter.cpp:
+        (JSC::Interpreter::execute):
+        (JSC::Interpreter::executeCall):
+        (JSC::Interpreter::executeConstruct):
+        (JSC::Interpreter::prepareForRepeatCall):
+        * interpreter/JSStack.h:
+        * interpreter/JSStackInlines.h:
+        * jit/JITCode.cpp:
+        (JSC::JITCode::execute):
+        * jit/JITStubs.h:
+        * jit/JITStubsMSVC64.asm: Added a FIXME.
+        * jit/JITStubsX86.h: Added a FIXME.
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::llint_throw_stack_overflow_error):
+        * llint/LLIntSlowPaths.h:
+        * llint/LLIntThunks.h:
+        * llint/LowLevelInterpreter64.asm:
+
 2013-12-20  Filip Pizlo  <fpi...@apple.com>
 
         Arity check slow path should ensure that when we return, we restore SP back to what the caller expects

Modified: branches/jsCStack/Source/_javascript_Core/interpreter/Interpreter.cpp (160946 => 160947)


--- branches/jsCStack/Source/_javascript_Core/interpreter/Interpreter.cpp	2013-12-21 00:44:36 UTC (rev 160946)
+++ branches/jsCStack/Source/_javascript_Core/interpreter/Interpreter.cpp	2013-12-21 00:56:24 UTC (rev 160947)
@@ -892,9 +892,6 @@
 
     ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.
 
-    if (UNLIKELY(!m_stack.entryCheck(codeBlock, 1)))
-        return checkedReturn(throwStackOverflowError(callFrame));
-
     ProtoCallFrame protoCallFrame;
     protoCallFrame.init(codeBlock, scope, 0, thisObj, 1);
 
@@ -955,9 +952,6 @@
     if (UNLIKELY(vm.watchdog.didFire(callFrame)))
         return throwTerminatedExecutionException(callFrame);
 
-    if (UNLIKELY(!m_stack.entryCheck(newCodeBlock, argsCount)))
-        return checkedReturn(throwStackOverflowError(callFrame));
-
     ProtoCallFrame protoCallFrame;
     protoCallFrame.init(newCodeBlock, scope, function, thisValue, argsCount, args.data());
 
@@ -973,7 +967,7 @@
         if (isJSCall)
             result = callData.js.functionExecutable->generatedJITCodeForCall()->execute(&vm, &protoCallFrame);
         else
-            result = JSValue::decode(callToNativeFunction(reinterpret_cast<void*>(callData.native.function), &vm.topCallFrame, &protoCallFrame));
+            result = JSValue::decode(callToNativeFunction(reinterpret_cast<void*>(callData.native.function), &vm, &protoCallFrame));
     }
 
     if (LegacyProfiler* profiler = vm.enabledProfiler())
@@ -1023,9 +1017,6 @@
     if (UNLIKELY(vm.watchdog.didFire(callFrame)))
         return throwTerminatedExecutionException(callFrame);
 
-    if (UNLIKELY(!m_stack.entryCheck(newCodeBlock, argsCount)))
-        return checkedReturn(throwStackOverflowError(callFrame));
-
     ProtoCallFrame protoCallFrame;
     protoCallFrame.init(newCodeBlock, scope, constructor, jsUndefined(), argsCount, args.data());
 
@@ -1041,7 +1032,7 @@
         if (isJSConstruct)
             result = constructData.js.functionExecutable->generatedJITCodeForConstruct()->execute(&vm, &protoCallFrame);
         else {
-            result = JSValue::decode(callToNativeFunction(reinterpret_cast<void*>(constructData.native.function), &vm.topCallFrame, &protoCallFrame));
+            result = JSValue::decode(callToNativeFunction(reinterpret_cast<void*>(constructData.native.function), &vm, &protoCallFrame));
 
             if (!callFrame->hadException())
                 RELEASE_ASSERT(result.isObject());
@@ -1076,11 +1067,6 @@
 
     size_t argsCount = argumentCountIncludingThis;
 
-    if (UNLIKELY(!m_stack.entryCheck(newCodeBlock, argsCount))) {
-        throwStackOverflowError(callFrame);
-        return CallFrameClosure();
-    }
-
     protoCallFrame->init(newCodeBlock, scope, function, jsUndefined(), argsCount, args);
     // Return the successful closure:
     CallFrameClosure result = { callFrame, protoCallFrame, function, functionExecutable, &vm, scope, newCodeBlock->numParameters(), argumentCountIncludingThis };
@@ -1182,9 +1168,6 @@
 
     ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.
 
-    if (UNLIKELY(!m_stack.entryCheck(codeBlock, 1)))
-        return checkedReturn(throwStackOverflowError(callFrame));
-
     ProtoCallFrame protoCallFrame;
     protoCallFrame.init(codeBlock, scope, 0, thisValue, 1);
 

Modified: branches/jsCStack/Source/_javascript_Core/interpreter/JSStack.h (160946 => 160947)


--- branches/jsCStack/Source/_javascript_Core/interpreter/JSStack.h	2013-12-21 00:44:36 UTC (rev 160946)
+++ branches/jsCStack/Source/_javascript_Core/interpreter/JSStack.h	2013-12-21 00:56:24 UTC (rev 160947)
@@ -101,8 +101,6 @@
         Register* startOfFrameFor(CallFrame*);
         Register* topOfStack();
 
-        bool entryCheck(class CodeBlock*, int);
-
         CallFrame* pushFrame(class CodeBlock*, JSScope*, int argsCount, JSObject* callee);
 
         void popFrame(CallFrame*);

Modified: branches/jsCStack/Source/_javascript_Core/interpreter/JSStackInlines.h (160946 => 160947)


--- branches/jsCStack/Source/_javascript_Core/interpreter/JSStackInlines.h	2013-12-21 00:44:36 UTC (rev 160946)
+++ branches/jsCStack/Source/_javascript_Core/interpreter/JSStackInlines.h	2013-12-21 00:56:24 UTC (rev 160947)
@@ -51,35 +51,6 @@
     return topOfFrameFor(callerFrame);
 }
 
-inline bool JSStack::entryCheck(class CodeBlock* codeBlock, int argsCount)
-{
-    Register* oldEnd = topOfStack();
-
-    // Ensure that we have enough space for the parameters:
-    size_t paddedArgsCount = argsCount;
-    if (codeBlock) {
-        size_t numParameters = codeBlock->numParameters();
-        if (paddedArgsCount < numParameters)
-            paddedArgsCount = numParameters;
-    }
-
-    Register* newCallFrameSlot = oldEnd - paddedArgsCount - (2 * JSStack::CallFrameHeaderSize) + 1;
-
-#if ENABLE(DEBUG_JSSTACK)
-    newCallFrameSlot -= JSStack::FenceSize;
-#endif
-
-    Register* topOfStack = newCallFrameSlot;
-    if (!!codeBlock)
-        topOfStack += codeBlock->stackPointerOffset();
-
-    // Ensure that we have the needed stack capacity to push the new frame:
-    if (!grow(topOfStack))
-        return false;
-
-    return true;
-}
-
 inline CallFrame* JSStack::pushFrame(class CodeBlock* codeBlock, JSScope* scope, int argsCount, JSObject* callee)
 {
     ASSERT(!!scope);

Modified: branches/jsCStack/Source/_javascript_Core/jit/JITCode.cpp (160946 => 160947)


--- branches/jsCStack/Source/_javascript_Core/jit/JITCode.cpp	2013-12-21 00:44:36 UTC (rev 160946)
+++ branches/jsCStack/Source/_javascript_Core/jit/JITCode.cpp	2013-12-21 00:56:24 UTC (rev 160947)
@@ -44,7 +44,7 @@
 
 JSValue JITCode::execute(VM* vm, ProtoCallFrame* protoCallFrame)
 {
-    JSValue result = JSValue::decode(callToJavaScript(executableAddress(), &vm->topCallFrame, protoCallFrame));
+    JSValue result = JSValue::decode(callToJavaScript(executableAddress(), vm, protoCallFrame));
     return vm->exception() ? jsNull() : result;
 }
 

Modified: branches/jsCStack/Source/_javascript_Core/jit/JITStubs.h (160946 => 160947)


--- branches/jsCStack/Source/_javascript_Core/jit/JITStubs.h	2013-12-21 00:44:36 UTC (rev 160946)
+++ branches/jsCStack/Source/_javascript_Core/jit/JITStubs.h	2013-12-21 00:56:24 UTC (rev 160947)
@@ -37,14 +37,13 @@
 #if ENABLE(JIT)
 
 #if OS(WINDOWS)
-class ExecState;
-class Register;
 struct ProtoCallFrame;
+class VM;
 
 extern "C" {
-    EncodedJSValue callToJavaScript(void*, ExecState**, ProtoCallFrame*);
+    EncodedJSValue callToJavaScript(void*, VM*, ProtoCallFrame*);
+    EncodedJSValue callToNativeFunction(void*, VM*, ProtoCallFrame*);
     void handleUncaughtException();
-    EncodedJSValue callToNativeFunction(void*, ExecState**, ProtoCallFrame*);
 }
 #endif
 

Modified: branches/jsCStack/Source/_javascript_Core/jit/JITStubsMSVC64.asm (160946 => 160947)


--- branches/jsCStack/Source/_javascript_Core/jit/JITStubsMSVC64.asm	2013-12-21 00:44:36 UTC (rev 160946)
+++ branches/jsCStack/Source/_javascript_Core/jit/JITStubsMSVC64.asm	2013-12-21 00:56:24 UTC (rev 160947)
@@ -35,6 +35,16 @@
     ;; FIXME: This function has not been tested as the Win 64 port doesn't currently use the JIT.
     ;; It is believed to be an accurate adaptation of the assembly created by the llint stub of the
     ;; same name with changes for agrument register differences.
+
+    ;; FIXME: This code is stale and need to be updated for the following:
+    ;; 1. The prototype is now:
+    ;;        EncodedJSValue callToJavaScript(void* code, VM*, ProtoCallFrame*)
+    ;;    The code below was implemented for a prototype of:
+    ;;        EncodedJSValue callToJavaScript(void* code, ExecState**, ProtoCallFrame*, Register*)
+    ;;
+    ;; 2. Need to add code for a stack check to ensure that we have enough stack space
+    ;;    for incoming args.
+
     int 3
     mov r10, qword ptr[rsp]
     push rbp

Modified: branches/jsCStack/Source/_javascript_Core/jit/JITStubsX86.h (160946 => 160947)


--- branches/jsCStack/Source/_javascript_Core/jit/JITStubsX86.h	2013-12-21 00:44:36 UTC (rev 160946)
+++ branches/jsCStack/Source/_javascript_Core/jit/JITStubsX86.h	2013-12-21 00:56:24 UTC (rev 160947)
@@ -206,6 +206,16 @@
 
     // FIXME: Since Windows doesn't use the LLInt, we have inline stubs here.
     // Until the LLInt is changed to support Windows, these stub needs to be updated.
+
+    // FIXME: This code is stale and need to be updated for the following:
+    // 1. The prototype is now:
+    //        EncodedJSValue callToJavaScript(void* code, VM*, ProtoCallFrame*)
+    //    I've left the old prototype in place to give context for what the implementation
+    //    below is doing.
+    //
+    // 2. Need to add code for a stack check to ensure that we have enough stack space
+    //    for incoming args.
+    
     __declspec(naked) EncodedJSValue callToJavaScript(void* code, ExecState**, ProtoCallFrame*, Register*)
     {
         __asm {

Modified: branches/jsCStack/Source/_javascript_Core/llint/LLIntSlowPaths.cpp (160946 => 160947)


--- branches/jsCStack/Source/_javascript_Core/llint/LLIntSlowPaths.cpp	2013-12-21 00:44:36 UTC (rev 160946)
+++ branches/jsCStack/Source/_javascript_Core/llint/LLIntSlowPaths.cpp	2013-12-21 00:56:24 UTC (rev 160947)
@@ -51,6 +51,7 @@
 #include "LowLevelInterpreter.h"
 #include "ObjectConstructor.h"
 #include "Operations.h"
+#include "ProtoCallFrame.h"
 #include "StructureRareDataInlines.h"
 #include <wtf/StringPrintStream.h>
 
@@ -1392,6 +1393,14 @@
     LLINT_END();
 }
 
+void llint_throw_stack_overflow_error(VM* vm, ProtoCallFrame* protoFrame)
+{
+    ExecState* exec = vm->topCallFrame;
+    if (!exec)
+        exec = protoFrame->scope()->globalObject()->globalExec();
+    throwStackOverflowError(exec);
+}
+
 } } // namespace JSC::LLInt
 
 #endif // ENABLE(LLINT)

Modified: branches/jsCStack/Source/_javascript_Core/llint/LLIntSlowPaths.h (160946 => 160947)


--- branches/jsCStack/Source/_javascript_Core/llint/LLIntSlowPaths.h	2013-12-21 00:44:36 UTC (rev 160946)
+++ branches/jsCStack/Source/_javascript_Core/llint/LLIntSlowPaths.h	2013-12-21 00:56:24 UTC (rev 160947)
@@ -36,6 +36,7 @@
 
 class ExecState;
 struct Instruction;
+struct ProtoCallFrame;
 
 namespace LLInt {
 
@@ -122,6 +123,7 @@
 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_resolve_scope);
 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_get_from_scope);
 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_put_to_scope);
+extern "C" void llint_throw_stack_overflow_error(VM*, ProtoCallFrame*);
 
 } } // namespace JSC::LLInt
 

Modified: branches/jsCStack/Source/_javascript_Core/llint/LLIntThunks.h (160946 => 160947)


--- branches/jsCStack/Source/_javascript_Core/llint/LLIntThunks.h	2013-12-21 00:44:36 UTC (rev 160946)
+++ branches/jsCStack/Source/_javascript_Core/llint/LLIntThunks.h	2013-12-21 00:56:24 UTC (rev 160947)
@@ -34,14 +34,12 @@
 
 namespace JSC {
 
-class ExecState;
-class Register;
 class VM;
 struct ProtoCallFrame;
 
 extern "C" {
-    EncodedJSValue callToJavaScript(void*, ExecState**, ProtoCallFrame*);
-    EncodedJSValue callToNativeFunction(void*, ExecState**, ProtoCallFrame*);
+    EncodedJSValue callToJavaScript(void*, VM*, ProtoCallFrame*);
+    EncodedJSValue callToNativeFunction(void*, VM*, ProtoCallFrame*);
 #if ENABLE(JIT)
     void handleUncaughtException();
 #endif

Modified: branches/jsCStack/Source/_javascript_Core/llint/LowLevelInterpreter64.asm (160946 => 160947)


--- branches/jsCStack/Source/_javascript_Core/llint/LowLevelInterpreter64.asm	2013-12-21 00:44:36 UTC (rev 160946)
+++ branches/jsCStack/Source/_javascript_Core/llint/LowLevelInterpreter64.asm	2013-12-21 00:56:24 UTC (rev 160947)
@@ -151,9 +151,8 @@
 macro doCallToJavaScript(makeCall)
     if X86_64
         const entry = t4
-        const vmTopCallFrame = t5
+        const vm = t5
         const protoCallFrame = t1
-        const topOfStack = t2
 
         const previousCFR = t0
         const previousPC = t6
@@ -162,9 +161,8 @@
         const temp3 = t6
     elsif ARM64
         const entry = a0
-        const vmTopCallFrame = a1
+        const vm = a1
         const protoCallFrame = a2
-        const topOfStack = a3
 
         const previousCFR = t5
         const previousPC = lr
@@ -181,12 +179,14 @@
 
     checkStackPointerAlignment(temp2, 0xbad0dc01)
 
-    # Allocate and initialize the sentinel frame.
+    # The stack host zone ensures that we have adequate space for the
+    # VMEntrySentinelFrame. Proceed with allocating and initializing the
+    # sentinel frame.
     move sp, cfr
     subp CallFrameHeaderSlots*8, cfr
     storep 0, ArgumentCount[cfr]
-    storep vmTopCallFrame, Callee[cfr]
-    loadp [vmTopCallFrame], temp2
+    storep vm, Callee[cfr]
+    loadp VM::topCallFrame[vm], temp2
     storep temp2, ScopeChain[cfr]
     storep 1, CodeBlock[cfr]
     storep previousPC, ReturnPC[cfr]
@@ -195,8 +195,27 @@
     loadi ProtoCallFrame::paddedArgCount[protoCallFrame], temp2
     addp CallFrameHeaderSlots, temp2, temp2
     lshiftp 3, temp2
-    subp cfr, temp2, sp
+    subp cfr, temp2, temp1
 
+    # Ensure that we have enough additional stack capacity for the incoming args,
+    # and the frame for the JS code we're executing. We need to do this check
+    # before we start copying the args from the protoCallFrame below.
+    bpaeq temp1, VM::m_jsStackLimit[vm], .stackHeightOK
+
+    move cfr, sp
+
+    if C_LOOP
+    # FIXME: Need to call stack check here to see if we can grow the stack.
+    # Will need to preserve registers so that we can recover if we do not end
+    # up throwing a StackOverflowError.
+    end
+
+    cCall2(_llint_throw_stack_overflow_error, vm, protoCallFrame)
+    callToJavaScriptEpilogue()
+    ret
+
+.stackHeightOK:
+    move temp1, sp
     move 5, temp1
 
 .copyHeaderLoop:
@@ -228,7 +247,7 @@
     jmp .copyArgsLoop
 
 .copyArgsDone:
-    storep sp, [vmTopCallFrame]
+    storep sp, VM::topCallFrame[vm]
 
     move 0xffff000000000000, csr1
     addp 2, csr1, csr2
@@ -243,9 +262,9 @@
     loadp CallerFrame[cfr], cfr
 
 .calleeFramePopped:
-    loadp Callee[cfr], temp2 # VM.topCallFrame
-    loadp ScopeChain[cfr], temp3
-    storep temp3, [temp2]
+    loadp Callee[cfr], temp2 # VM
+    loadp ScopeChain[cfr], temp3 # previous topCallFrame
+    storep temp3, VM::topCallFrame[temp2]
 
     checkStackPointerAlignment(temp3, 0xbad0dc04)
 
@@ -285,9 +304,9 @@
     # returning to the caller C frame.
     loadp CallerFrame[cfr], cfr
 
-    loadp Callee[cfr], t3 # VM.topCallFrame
-    loadp ScopeChain[cfr], t6
-    storep t6, [t3]
+    loadp Callee[cfr], t3 # VM
+    loadp ScopeChain[cfr], t6 # previous topCallFrame
+    storep t6, VM::topCallFrame[t3]
 
     callToJavaScriptEpilogue()
     ret
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to