Changeset 160947 in webkit


Ignore:
Timestamp:
Dec 20, 2013 4:56:24 PM (10 years ago)
Author:
mark.lam@apple.com
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.

  1. 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.
  1. 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:
Location:
branches/jsCStack/Source/JavaScriptCore
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • branches/jsCStack/Source/JavaScriptCore/ChangeLog

    r160936 r160947  
     12013-12-20  Mark Lam  <mark.lam@apple.com>
     2
     3        CStack: callToJavaScript should do stack check for incoming args.
     4        https://bugs.webkit.org/show_bug.cgi?id=126088.
     5
     6        Not yet reviewed.
     7
     8        1. Change callToJavaScript()'s prototype to:
     9               EncodedJSValue callToJavaScript(void*, VM*, ProtoCallFrame*);
     10
     11           We now pass VM* instead of &vm.topCallFrame for the second argument.
     12           This gives us greater utility out of that arg.
     13           We also now save the VM* in the VMEntrySentinelFrame instead of
     14           &vm.topCallFrame.
     15
     16        2. Change callToJavaScript() to do a stack check to ensure that we have
     17           adequate stack space to copy all the args from the protoCallFrame.
     18           If not, it'll throw a StackOverflowError.
     19
     20        3. Removed JSStack::entryCheck() and calls to it.
     21
     22           callToJavaScript now takes care of the stack check that ensures
     23           adequate stack space for incoming args.
     24           callToJavaScript does assume that we have adequate stack space for
     25           the VMEntrySentinelFrame, but that is ensured by our stack host zone.
     26
     27        Changes to callToJavaScript are done in the doCallToJavaScript macro.
     28        Hence, all the changes apply to callToNativeFunction as well.
     29
     30        * interpreter/Interpreter.cpp:
     31        (JSC::Interpreter::execute):
     32        (JSC::Interpreter::executeCall):
     33        (JSC::Interpreter::executeConstruct):
     34        (JSC::Interpreter::prepareForRepeatCall):
     35        * interpreter/JSStack.h:
     36        * interpreter/JSStackInlines.h:
     37        * jit/JITCode.cpp:
     38        (JSC::JITCode::execute):
     39        * jit/JITStubs.h:
     40        * jit/JITStubsMSVC64.asm: Added a FIXME.
     41        * jit/JITStubsX86.h: Added a FIXME.
     42        * llint/LLIntSlowPaths.cpp:
     43        (JSC::LLInt::llint_throw_stack_overflow_error):
     44        * llint/LLIntSlowPaths.h:
     45        * llint/LLIntThunks.h:
     46        * llint/LowLevelInterpreter64.asm:
     47
    1482013-12-20  Filip Pizlo  <fpizlo@apple.com>
    249
  • branches/jsCStack/Source/JavaScriptCore/interpreter/Interpreter.cpp

    r160831 r160947  
    893893    ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.
    894894
    895     if (UNLIKELY(!m_stack.entryCheck(codeBlock, 1)))
    896         return checkedReturn(throwStackOverflowError(callFrame));
    897 
    898895    ProtoCallFrame protoCallFrame;
    899896    protoCallFrame.init(codeBlock, scope, 0, thisObj, 1);
     
    956953        return throwTerminatedExecutionException(callFrame);
    957954
    958     if (UNLIKELY(!m_stack.entryCheck(newCodeBlock, argsCount)))
    959         return checkedReturn(throwStackOverflowError(callFrame));
    960 
    961955    ProtoCallFrame protoCallFrame;
    962956    protoCallFrame.init(newCodeBlock, scope, function, thisValue, argsCount, args.data());
     
    974968            result = callData.js.functionExecutable->generatedJITCodeForCall()->execute(&vm, &protoCallFrame);
    975969        else
    976             result = JSValue::decode(callToNativeFunction(reinterpret_cast<void*>(callData.native.function), &vm.topCallFrame, &protoCallFrame));
     970            result = JSValue::decode(callToNativeFunction(reinterpret_cast<void*>(callData.native.function), &vm, &protoCallFrame));
    977971    }
    978972
     
    10241018        return throwTerminatedExecutionException(callFrame);
    10251019
    1026     if (UNLIKELY(!m_stack.entryCheck(newCodeBlock, argsCount)))
    1027         return checkedReturn(throwStackOverflowError(callFrame));
    1028 
    10291020    ProtoCallFrame protoCallFrame;
    10301021    protoCallFrame.init(newCodeBlock, scope, constructor, jsUndefined(), argsCount, args.data());
     
    10421033            result = constructData.js.functionExecutable->generatedJITCodeForConstruct()->execute(&vm, &protoCallFrame);
    10431034        else {
    1044             result = JSValue::decode(callToNativeFunction(reinterpret_cast<void*>(constructData.native.function), &vm.topCallFrame, &protoCallFrame));
     1035            result = JSValue::decode(callToNativeFunction(reinterpret_cast<void*>(constructData.native.function), &vm, &protoCallFrame));
    10451036
    10461037            if (!callFrame->hadException())
     
    10761067
    10771068    size_t argsCount = argumentCountIncludingThis;
    1078 
    1079     if (UNLIKELY(!m_stack.entryCheck(newCodeBlock, argsCount))) {
    1080         throwStackOverflowError(callFrame);
    1081         return CallFrameClosure();
    1082     }
    10831069
    10841070    protoCallFrame->init(newCodeBlock, scope, function, jsUndefined(), argsCount, args);
     
    11821168
    11831169    ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.
    1184 
    1185     if (UNLIKELY(!m_stack.entryCheck(codeBlock, 1)))
    1186         return checkedReturn(throwStackOverflowError(callFrame));
    11871170
    11881171    ProtoCallFrame protoCallFrame;
  • branches/jsCStack/Source/JavaScriptCore/interpreter/JSStack.h

    r160835 r160947  
    102102        Register* topOfStack();
    103103
    104         bool entryCheck(class CodeBlock*, int);
    105 
    106104        CallFrame* pushFrame(class CodeBlock*, JSScope*, int argsCount, JSObject* callee);
    107105
  • branches/jsCStack/Source/JavaScriptCore/interpreter/JSStackInlines.h

    r160835 r160947  
    5252}
    5353
    54 inline bool JSStack::entryCheck(class CodeBlock* codeBlock, int argsCount)
    55 {
    56     Register* oldEnd = topOfStack();
    57 
    58     // Ensure that we have enough space for the parameters:
    59     size_t paddedArgsCount = argsCount;
    60     if (codeBlock) {
    61         size_t numParameters = codeBlock->numParameters();
    62         if (paddedArgsCount < numParameters)
    63             paddedArgsCount = numParameters;
    64     }
    65 
    66     Register* newCallFrameSlot = oldEnd - paddedArgsCount - (2 * JSStack::CallFrameHeaderSize) + 1;
    67 
    68 #if ENABLE(DEBUG_JSSTACK)
    69     newCallFrameSlot -= JSStack::FenceSize;
    70 #endif
    71 
    72     Register* topOfStack = newCallFrameSlot;
    73     if (!!codeBlock)
    74         topOfStack += codeBlock->stackPointerOffset();
    75 
    76     // Ensure that we have the needed stack capacity to push the new frame:
    77     if (!grow(topOfStack))
    78         return false;
    79 
    80     return true;
    81 }
    82 
    8354inline CallFrame* JSStack::pushFrame(class CodeBlock* codeBlock, JSScope* scope, int argsCount, JSObject* callee)
    8455{
  • branches/jsCStack/Source/JavaScriptCore/jit/JITCode.cpp

    r160936 r160947  
    4545JSValue JITCode::execute(VM* vm, ProtoCallFrame* protoCallFrame)
    4646{
    47     JSValue result = JSValue::decode(callToJavaScript(executableAddress(), &vm->topCallFrame, protoCallFrame));
     47    JSValue result = JSValue::decode(callToJavaScript(executableAddress(), vm, protoCallFrame));
    4848    return vm->exception() ? jsNull() : result;
    4949}
  • branches/jsCStack/Source/JavaScriptCore/jit/JITStubs.h

    r160660 r160947  
    3838
    3939#if OS(WINDOWS)
    40 class ExecState;
    41 class Register;
    4240struct ProtoCallFrame;
     41class VM;
    4342
    4443extern "C" {
    45     EncodedJSValue callToJavaScript(void*, ExecState**, ProtoCallFrame*);
     44    EncodedJSValue callToJavaScript(void*, VM*, ProtoCallFrame*);
     45    EncodedJSValue callToNativeFunction(void*, VM*, ProtoCallFrame*);
    4646    void handleUncaughtException();
    47     EncodedJSValue callToNativeFunction(void*, ExecState**, ProtoCallFrame*);
    4847}
    4948#endif
  • branches/jsCStack/Source/JavaScriptCore/jit/JITStubsMSVC64.asm

    r160497 r160947  
    3636    ;; It is believed to be an accurate adaptation of the assembly created by the llint stub of the
    3737    ;; same name with changes for agrument register differences.
     38
     39    ;; FIXME: This code is stale and need to be updated for the following:
     40    ;; 1. The prototype is now:
     41    ;;        EncodedJSValue callToJavaScript(void* code, VM*, ProtoCallFrame*)
     42    ;;    The code below was implemented for a prototype of:
     43    ;;        EncodedJSValue callToJavaScript(void* code, ExecState**, ProtoCallFrame*, Register*)
     44    ;;
     45    ;; 2. Need to add code for a stack check to ensure that we have enough stack space
     46    ;;    for incoming args.
     47
    3848    int 3
    3949    mov r10, qword ptr[rsp]
  • branches/jsCStack/Source/JavaScriptCore/jit/JITStubsX86.h

    r160497 r160947  
    207207    // FIXME: Since Windows doesn't use the LLInt, we have inline stubs here.
    208208    // Until the LLInt is changed to support Windows, these stub needs to be updated.
     209
     210    // FIXME: This code is stale and need to be updated for the following:
     211    // 1. The prototype is now:
     212    //        EncodedJSValue callToJavaScript(void* code, VM*, ProtoCallFrame*)
     213    //    I've left the old prototype in place to give context for what the implementation
     214    //    below is doing.
     215    //
     216    // 2. Need to add code for a stack check to ensure that we have enough stack space
     217    //    for incoming args.
     218   
    209219    __declspec(naked) EncodedJSValue callToJavaScript(void* code, ExecState**, ProtoCallFrame*, Register*)
    210220    {
  • branches/jsCStack/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp

    r160936 r160947  
    5252#include "ObjectConstructor.h"
    5353#include "Operations.h"
     54#include "ProtoCallFrame.h"
    5455#include "StructureRareDataInlines.h"
    5556#include <wtf/StringPrintStream.h>
     
    13931394}
    13941395
     1396void llint_throw_stack_overflow_error(VM* vm, ProtoCallFrame* protoFrame)
     1397{
     1398    ExecState* exec = vm->topCallFrame;
     1399    if (!exec)
     1400        exec = protoFrame->scope()->globalObject()->globalExec();
     1401    throwStackOverflowError(exec);
     1402}
     1403
    13951404} } // namespace JSC::LLInt
    13961405
  • branches/jsCStack/Source/JavaScriptCore/llint/LLIntSlowPaths.h

    r160831 r160947  
    3737class ExecState;
    3838struct Instruction;
     39struct ProtoCallFrame;
    3940
    4041namespace LLInt {
     
    123124LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_get_from_scope);
    124125LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_put_to_scope);
     126extern "C" void llint_throw_stack_overflow_error(VM*, ProtoCallFrame*);
    125127
    126128} } // namespace JSC::LLInt
  • branches/jsCStack/Source/JavaScriptCore/llint/LLIntThunks.h

    r160660 r160947  
    3535namespace JSC {
    3636
    37 class ExecState;
    38 class Register;
    3937class VM;
    4038struct ProtoCallFrame;
    4139
    4240extern "C" {
    43     EncodedJSValue callToJavaScript(void*, ExecState**, ProtoCallFrame*);
    44     EncodedJSValue callToNativeFunction(void*, ExecState**, ProtoCallFrame*);
     41    EncodedJSValue callToJavaScript(void*, VM*, ProtoCallFrame*);
     42    EncodedJSValue callToNativeFunction(void*, VM*, ProtoCallFrame*);
    4543#if ENABLE(JIT)
    4644    void handleUncaughtException();
  • branches/jsCStack/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm

    r160936 r160947  
    152152    if X86_64
    153153        const entry = t4
    154         const vmTopCallFrame = t5
     154        const vm = t5
    155155        const protoCallFrame = t1
    156         const topOfStack = t2
    157156
    158157        const previousCFR = t0
     
    163162    elsif ARM64
    164163        const entry = a0
    165         const vmTopCallFrame = a1
     164        const vm = a1
    166165        const protoCallFrame = a2
    167         const topOfStack = a3
    168166
    169167        const previousCFR = t5
     
    182180    checkStackPointerAlignment(temp2, 0xbad0dc01)
    183181
    184     # Allocate and initialize the sentinel frame.
     182    # The stack host zone ensures that we have adequate space for the
     183    # VMEntrySentinelFrame. Proceed with allocating and initializing the
     184    # sentinel frame.
    185185    move sp, cfr
    186186    subp CallFrameHeaderSlots*8, cfr
    187187    storep 0, ArgumentCount[cfr]
    188     storep vmTopCallFrame, Callee[cfr]
    189     loadp [vmTopCallFrame], temp2
     188    storep vm, Callee[cfr]
     189    loadp VM::topCallFrame[vm], temp2
    190190    storep temp2, ScopeChain[cfr]
    191191    storep 1, CodeBlock[cfr]
     
    196196    addp CallFrameHeaderSlots, temp2, temp2
    197197    lshiftp 3, temp2
    198     subp cfr, temp2, sp
    199 
     198    subp cfr, temp2, temp1
     199
     200    # Ensure that we have enough additional stack capacity for the incoming args,
     201    # and the frame for the JS code we're executing. We need to do this check
     202    # before we start copying the args from the protoCallFrame below.
     203    bpaeq temp1, VM::m_jsStackLimit[vm], .stackHeightOK
     204
     205    move cfr, sp
     206
     207    if C_LOOP
     208    # FIXME: Need to call stack check here to see if we can grow the stack.
     209    # Will need to preserve registers so that we can recover if we do not end
     210    # up throwing a StackOverflowError.
     211    end
     212
     213    cCall2(_llint_throw_stack_overflow_error, vm, protoCallFrame)
     214    callToJavaScriptEpilogue()
     215    ret
     216
     217.stackHeightOK:
     218    move temp1, sp
    200219    move 5, temp1
    201220
     
    229248
    230249.copyArgsDone:
    231     storep sp, [vmTopCallFrame]
     250    storep sp, VM::topCallFrame[vm]
    232251
    233252    move 0xffff000000000000, csr1
     
    244263
    245264.calleeFramePopped:
    246     loadp Callee[cfr], temp2 # VM.topCallFrame
    247     loadp ScopeChain[cfr], temp3
    248     storep temp3, [temp2]
     265    loadp Callee[cfr], temp2 # VM
     266    loadp ScopeChain[cfr], temp3 # previous topCallFrame
     267    storep temp3, VM::topCallFrame[temp2]
    249268
    250269    checkStackPointerAlignment(temp3, 0xbad0dc04)
     
    286305    loadp CallerFrame[cfr], cfr
    287306
    288     loadp Callee[cfr], t3 # VM.topCallFrame
    289     loadp ScopeChain[cfr], t6
    290     storep t6, [t3]
     307    loadp Callee[cfr], t3 # VM
     308    loadp ScopeChain[cfr], t6 # previous topCallFrame
     309    storep t6, VM::topCallFrame[t3]
    291310
    292311    callToJavaScriptEpilogue()
Note: See TracChangeset for help on using the changeset viewer.