Ignore:
Timestamp:
Aug 15, 2014, 6:45:40 PM (11 years ago)
Author:
[email protected]
Message:

Change callToJavaScript and callToNativeFunction so their callFrames match the native calling conventions
https://bugs.webkit.org/show_bug.cgi?id=131578

Reviewed by Geoffrey Garen.

Renamed callToJavaScript and callToNativeFunction to vmEntryToJavaScript and vmEntryToNative,
respectively. Eliminated the sentinel frame and replaced it with the structure VMEntryRecord
that appears in the "locals" area of a VM entry stack frame. Changed the order that
vmEntryToJavaScript and vmEntryToNative creates their stack frames to be native calling
convention compliant. That is to save prior frame pointer, save callee save registers, then
allocate and populate the VMEntryRecord, and finally allocate a CallFrame for the JS function
that vmEntryToJavaScript will invoke. The top most vm entry frame pointer is saved in
VM::topVMEntryFrame. The vmEntry functions save prior contents of VM::topVMEntryFrame
along with the VM and VM::topCallFrame in the VMEntryRecord it places on the stack. Starting
at VM::topCallFrame, the stack can be walked using these VMEntryRecords.

Arbitrary stack unwinding is now handled either iteratively by loading VM::topVMEntryFrame
into a local variable and using CallFrame::callerFrame(VMEntryFrame*&) or by using StackVisitor.
Given that the stack is effectively a singly linked list, general stack unwinding needs to use
one of these two methods.

Addition of VMEntryRecord.h

  • bytecode/BytecodeList.json:

Renaming of llint helper opcodes due to renaming callToJavaScript and callToNativeFunction.

  • debugger/Debugger.cpp:

(JSC::Debugger::stepOutOfFunction):
(JSC::Debugger::returnEvent):
(JSC::Debugger::didExecuteProgram):

  • jsc.cpp:

(functionDumpCallFrame):

  • jit/JITOperations.cpp:

Changed unwinding to use CallFrame::callerFrame(VMEntryFrame*&).

  • bytecode/CodeBlock.cpp:

(JSC::RecursionCheckFunctor::RecursionCheckFunctor):
(JSC::RecursionCheckFunctor::operator()):
(JSC::RecursionCheckFunctor::didRecurse):
(JSC::CodeBlock::noticeIncomingCall):

  • debugger/DebuggerCallFrame.cpp:

(JSC::FindCallerMidStackFunctor::FindCallerMidStackFunctor):
(JSC::FindCallerMidStackFunctor::operator()):
(JSC::FindCallerMidStackFunctor::getCallerFrame):
(JSC::DebuggerCallFrame::callerFrame):

  • interpreter/VMInspector.cpp:

(JSC::CountFramesFunctor::CountFramesFunctor):
(JSC::CountFramesFunctor::operator()):
(JSC::CountFramesFunctor::count):
(JSC::VMInspector::countFrames):

  • runtime/VM.cpp:

(JSC::VM::VM):
(JSC::FindFirstCallerFrameWithCodeblockFunctor::FindFirstCallerFrameWithCodeblockFunctor):
(JSC::FindFirstCallerFrameWithCodeblockFunctor::operator()):
(JSC::FindFirstCallerFrameWithCodeblockFunctor::foundCallFrame):
(JSC::FindFirstCallerFrameWithCodeblockFunctor::index):
(JSC::VM::throwException):
Changed unwinding to use StackVisitor including added functor classes.

  • interpreter/CallFrame.cpp:

(JSC::CallFrame::callerFrame):
Added new flavor of callerFrame() that can iteratively unwind the stack.

  • interpreter/CallFrame.h:

(JSC::ExecState::callerFrame): Changed callerFrame() to use private common helper.
(JSC::ExecState::callerFrameOrVMEntryFrame): Deleted.
(JSC::ExecState::isVMEntrySentinel): Deleted.
(JSC::ExecState::vmEntrySentinelCallerFrame): Deleted.
(JSC::ExecState::initializeVMEntrySentinelFrame): Deleted.
(JSC::ExecState::callerFrameSkippingVMEntrySentinel): Deleted.
(JSC::ExecState::vmEntrySentinelCodeBlock): Deleted.

  • interpreter/CallFrame.h:

(JSC::ExecState::init):
(JSC::ExecState::topOfFrame):
(JSC::ExecState::currentVPC):
(JSC::ExecState::setCurrentVPC):
Eliminated unneded checking of sentinel frame.

  • interpreter/Interpreter.cpp:

(JSC::unwindCallFrame):
(JSC::Interpreter::getStackTrace): Updated for unwidning changes.
(JSC::Interpreter::unwind): Eliminated unneeded sentinel frame check.

  • interpreter/Interpreter.cpp:

(JSC::Interpreter::executeCall):
(JSC::Interpreter::executeConstruct):

  • jit/JITStubs.h:
  • llint/LLIntThunks.cpp:

(JSC::callToJavaScript): Deleted.
(JSC::callToNativetion): Deleted.
(JSC::vmEntryToJavaScript):
(JSC::vmEntryToNative):

  • llint/LLIntThunks.h:

Updated for vmEntryToJavaScript and vmEntryToNative name changes.

  • interpreter/Interpreter.h:

(JSC::TopCallFrameSetter::TopCallFrameSetter):
(JSC::TopCallFrameSetter::~TopCallFrameSetter):
Eliminated unneeded sentinel frame check.

  • interpreter/Interpreter.h:

(JSC::NativeCallFrameTracer::NativeCallFrameTracer):
Removed sentinel specific constructor.

  • interpreter/StackVisitor.cpp:

(JSC::StackVisitor::StackVisitor):
(JSC::StackVisitor::readFrame):
(JSC::StackVisitor::readNonInlinedFrame):
(JSC::StackVisitor::readInlinedFrame):
(JSC::StackVisitor::Frame::print):

  • interpreter/StackVisitor.h:

(JSC::StackVisitor::Frame::callerIsVMEntry):
Changes for unwinding using CallFrame::callerFrame(VMEntryFrame*&). Also added field that
indicates when about to step over a VM entry frame.

  • interpreter/VMEntryRecord.h: Added.

(JSC::VMEntryRecord::prevTopCallFrame):
(JSC::VMEntryRecord::prevTopVMEntryFrame):
New struct to record prior state of VM's notion of VM entry and top call frames.

  • jit/JITCode.cpp:

(JSC::JITCode::execute):
Use new vmEntryToJavaScript and vmEntryToNative name.

  • llint/LLIntOffsetsExtractor.cpp: Added include for VMEntryRecord.h.
  • llint/LowLevelInterpreter.asm:
  • llint/LowLevelInterpreter32_64.asm:
  • llint/LowLevelInterpreter64.asm:

Offline assembly implementation of creating stack frame with VMEntryRecord and well as restoring
relevent VM fields when exiting the VM. Added a helper that returns a VMEntryRecord given
a pointer to the VM entry frame.

  • llint/LLIntThunks.cpp:

(JSC::vmEntryRecord):

  • llint/LowLevelInterpreter.cpp:

(JSC::CLoop::execute):
C Loop changes to mirror the assembly changes.

  • runtime/VM.h:

Added topVMEntryFrame field.

Location:
trunk/Source/JavaScriptCore/bytecode
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/bytecode/BytecodeList.json

    r172614 r172665  
    140140            { "name" : "getHostCallReturnValue" },
    141141            { "name" : "llint_return_to_host" },
    142             { "name" : "llint_call_to_javascript" },
    143             { "name" : "llint_call_to_native_function" },
     142            { "name" : "llint_vm_entry_to_javascript" },
     143            { "name" : "llint_vm_entry_to_native" },
    144144            { "name" : "llint_cloop_did_return_from_js_1" },
    145145            { "name" : "llint_cloop_did_return_from_js_2" },
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp

    r172614 r172665  
    6060#include "RepatchBuffer.h"
    6161#include "SlotVisitorInlines.h"
     62#include "StackVisitor.h"
    6263#include "UnlinkedInstructionStream.h"
    6364#include <wtf/BagToHashMap.h>
     
    31603161}
    31613162
     3163class RecursionCheckFunctor {
     3164public:
     3165    RecursionCheckFunctor(CallFrame* startCallFrame, CodeBlock* codeBlock, unsigned depthToCheck)
     3166        : m_startCallFrame(startCallFrame)
     3167        , m_codeBlock(codeBlock)
     3168        , m_depthToCheck(depthToCheck)
     3169        , m_foundStartCallFrame(false)
     3170        , m_didRecurse(false)
     3171    { }
     3172
     3173    StackVisitor::Status operator()(StackVisitor& visitor)
     3174    {
     3175        CallFrame* currentCallFrame = visitor->callFrame();
     3176
     3177        if (currentCallFrame == m_startCallFrame)
     3178            m_foundStartCallFrame = true;
     3179
     3180        if (m_foundStartCallFrame) {
     3181            if (visitor->callFrame()->codeBlock() == m_codeBlock) {
     3182                m_didRecurse = true;
     3183                return StackVisitor::Done;
     3184            }
     3185
     3186            if (!m_depthToCheck--)
     3187                return StackVisitor::Done;
     3188        }
     3189
     3190        return StackVisitor::Continue;
     3191    }
     3192
     3193    bool didRecurse() const { return m_didRecurse; }
     3194
     3195private:
     3196    CallFrame* m_startCallFrame;
     3197    CodeBlock* m_codeBlock;
     3198    unsigned m_depthToCheck;
     3199    bool m_foundStartCallFrame;
     3200    bool m_didRecurse;
     3201};
     3202
    31623203void CodeBlock::noticeIncomingCall(ExecState* callerFrame)
    31633204{
     
    32073248        return;
    32083249    }
    3209    
    3210     ExecState* frame = callerFrame;
    3211     for (unsigned i = Options::maximumInliningDepth(); i--; frame = frame->callerFrame()) {
    3212         if (frame->isVMEntrySentinel())
    3213             break;
    3214         if (frame->codeBlock() == this) {
    3215             // Recursive calls won't be inlined.
    3216             if (Options::verboseCallLink())
    3217                 dataLog("    Clearing SABI because recursion was detected.\n");
    3218             m_shouldAlwaysBeInlined = false;
    3219             return;
    3220         }
    3221     }
    3222    
     3250
     3251    // Recursive calls won't be inlined.
     3252    RecursionCheckFunctor functor(callerFrame, this, Options::maximumInliningDepth());
     3253    vm()->topCallFrame->iterate(functor);
     3254
     3255    if (functor.didRecurse()) {
     3256        if (Options::verboseCallLink())
     3257            dataLog("    Clearing SABI because recursion was detected.\n");
     3258        m_shouldAlwaysBeInlined = false;
     3259        return;
     3260    }
     3261
    32233262    RELEASE_ASSERT(callerCodeBlock->m_capabilityLevelState != DFG::CapabilityLevelNotSet);
    32243263   
Note: See TracChangeset for help on using the changeset viewer.