Changeset 122392 in webkit


Ignore:
Timestamp:
Jul 11, 2012 5:12:03 PM (12 years ago)
Author:
fpizlo@apple.com
Message:

DFG should have fast virtual calls
https://bugs.webkit.org/show_bug.cgi?id=90924

Source/JavaScriptCore:

Reviewed by Gavin Barraclough.

Implements virtual call support in the style of the old JIT, with the
caveat that we still use the same slow path for both InternalFunction
calls and JSFunction calls. Also rationalized the way that our
CodeOrigin indices tie into exception checks (previously it was a
strange one-to-one mapping with fairly limited assertions; now it's a
one-to-many mapping for CodeOrigins to exception checks, respectively).
I also took the opportunity to clean up
CallLinkInfo::callReturnLocation, which previously was either a Call or
a NearCall. Now it's just a NearCall. As well, exceptions during slow
path call resolution are now handled by returning an exception throwing
thunk rather than returning null. And finally, I made a few things
public that were previously private-with-lots-of-friends, because I
truly despise the thought of listing each thunk generating function as
a friend of JSValue and friends.

  • bytecode/CallLinkInfo.cpp:

(JSC::CallLinkInfo::unlink):

  • bytecode/CallLinkInfo.h:

(CallLinkInfo):

  • bytecode/CodeOrigin.h:

(JSC::CodeOrigin::CodeOrigin):
(JSC::CodeOrigin::isSet):

  • dfg/DFGAssemblyHelpers.h:

(JSC::DFG::AssemblyHelpers::AssemblyHelpers):

  • dfg/DFGCCallHelpers.h:

(JSC::DFG::CCallHelpers::CCallHelpers):

  • dfg/DFGGPRInfo.h:

(GPRInfo):

  • dfg/DFGJITCompiler.cpp:

(JSC::DFG::JITCompiler::link):
(JSC::DFG::JITCompiler::compileFunction):

  • dfg/DFGJITCompiler.h:

(JSC::DFG::CallBeginToken::CallBeginToken):
(JSC::DFG::CallBeginToken::~CallBeginToken):
(CallBeginToken):
(JSC::DFG::CallBeginToken::set):
(JSC::DFG::CallBeginToken::registerWithExceptionCheck):
(JSC::DFG::CallBeginToken::codeOrigin):
(JSC::DFG::CallExceptionRecord::CallExceptionRecord):
(CallExceptionRecord):
(JSC::DFG::JITCompiler::currentCodeOriginIndex):
(JITCompiler):
(JSC::DFG::JITCompiler::beginCall):
(JSC::DFG::JITCompiler::notifyCall):
(JSC::DFG::JITCompiler::prepareForExceptionCheck):
(JSC::DFG::JITCompiler::addExceptionCheck):
(JSC::DFG::JITCompiler::addFastExceptionCheck):

  • dfg/DFGOperations.cpp:
  • dfg/DFGRepatch.cpp:

(JSC::DFG::dfgLinkFor):

  • dfg/DFGSpeculativeJIT.h:

(JSC::DFG::SpeculativeJIT::appendCallWithExceptionCheck):

  • dfg/DFGSpeculativeJIT32_64.cpp:

(JSC::DFG::SpeculativeJIT::emitCall):

  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::emitCall):

  • dfg/DFGThunks.cpp:

(JSC::DFG::emitPointerValidation):
(DFG):
(JSC::DFG::throwExceptionFromCallSlowPathGenerator):
(JSC::DFG::slowPathFor):
(JSC::DFG::linkForThunkGenerator):
(JSC::DFG::linkCallThunkGenerator):
(JSC::DFG::linkConstructThunkGenerator):
(JSC::DFG::virtualForThunkGenerator):
(JSC::DFG::virtualCallThunkGenerator):
(JSC::DFG::virtualConstructThunkGenerator):

  • dfg/DFGThunks.h:

(DFG):

  • jit/JIT.cpp:

(JSC::JIT::privateCompile):
(JSC::JIT::linkFor):

  • runtime/Executable.h:

(ExecutableBase):
(JSC::ExecutableBase::offsetOfJITCodeFor):
(JSC::ExecutableBase::offsetOfNumParametersFor):

  • runtime/JSValue.h:

(JSValue):

LayoutTests:

Rubber stamped by Oliver Hunt.

This changes which piece of code appears on top of the stack at the point of a stack
overflow. As far as Oliver and I can tell, it doesn't matter, so I just rebased the
test.

  • fast/js/stack-trace-expected.txt:
Location:
trunk
Files:
21 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r122386 r122392  
     12012-07-11  Filip Pizlo  <fpizlo@apple.com>
     2
     3        DFG should have fast virtual calls
     4        https://bugs.webkit.org/show_bug.cgi?id=90924
     5
     6        Rubber stamped by Oliver Hunt.
     7
     8        This changes which piece of code appears on top of the stack at the point of a stack
     9        overflow. As far as Oliver and I can tell, it doesn't matter, so I just rebased the
     10        test.
     11
     12        * fast/js/stack-trace-expected.txt:
     13
    1142012-07-11  Adam Barth  <abarth@webkit.org>
    215
  • trunk/LayoutTests/fast/js/stack-trace-expected.txt

    r115861 r122392  
    152152
    153153--> Stack Trace:
    154     0   selfRecursive2 at stack-trace.js:58
     154    0   selfRecursive2 at stack-trace.js:62
    155155    1   selfRecursive2 at stack-trace.js:62
    156156    2   selfRecursive2 at stack-trace.js:62
  • trunk/Source/JavaScriptCore/ChangeLog

    r122388 r122392  
     12012-07-11  Filip Pizlo  <fpizlo@apple.com>
     2
     3        DFG should have fast virtual calls
     4        https://bugs.webkit.org/show_bug.cgi?id=90924
     5
     6        Reviewed by Gavin Barraclough.
     7       
     8        Implements virtual call support in the style of the old JIT, with the
     9        caveat that we still use the same slow path for both InternalFunction
     10        calls and JSFunction calls. Also rationalized the way that our
     11        CodeOrigin indices tie into exception checks (previously it was a
     12        strange one-to-one mapping with fairly limited assertions; now it's a
     13        one-to-many mapping for CodeOrigins to exception checks, respectively).
     14        I also took the opportunity to clean up
     15        CallLinkInfo::callReturnLocation, which previously was either a Call or
     16        a NearCall. Now it's just a NearCall. As well, exceptions during slow
     17        path call resolution are now handled by returning an exception throwing
     18        thunk rather than returning null. And finally, I made a few things
     19        public that were previously private-with-lots-of-friends, because I
     20        truly despise the thought of listing each thunk generating function as
     21        a friend of JSValue and friends.
     22       
     23        * bytecode/CallLinkInfo.cpp:
     24        (JSC::CallLinkInfo::unlink):
     25        * bytecode/CallLinkInfo.h:
     26        (CallLinkInfo):
     27        * bytecode/CodeOrigin.h:
     28        (JSC::CodeOrigin::CodeOrigin):
     29        (JSC::CodeOrigin::isSet):
     30        * dfg/DFGAssemblyHelpers.h:
     31        (JSC::DFG::AssemblyHelpers::AssemblyHelpers):
     32        * dfg/DFGCCallHelpers.h:
     33        (JSC::DFG::CCallHelpers::CCallHelpers):
     34        * dfg/DFGGPRInfo.h:
     35        (GPRInfo):
     36        * dfg/DFGJITCompiler.cpp:
     37        (JSC::DFG::JITCompiler::link):
     38        (JSC::DFG::JITCompiler::compileFunction):
     39        * dfg/DFGJITCompiler.h:
     40        (JSC::DFG::CallBeginToken::CallBeginToken):
     41        (JSC::DFG::CallBeginToken::~CallBeginToken):
     42        (CallBeginToken):
     43        (JSC::DFG::CallBeginToken::set):
     44        (JSC::DFG::CallBeginToken::registerWithExceptionCheck):
     45        (JSC::DFG::CallBeginToken::codeOrigin):
     46        (JSC::DFG::CallExceptionRecord::CallExceptionRecord):
     47        (CallExceptionRecord):
     48        (JSC::DFG::JITCompiler::currentCodeOriginIndex):
     49        (JITCompiler):
     50        (JSC::DFG::JITCompiler::beginCall):
     51        (JSC::DFG::JITCompiler::notifyCall):
     52        (JSC::DFG::JITCompiler::prepareForExceptionCheck):
     53        (JSC::DFG::JITCompiler::addExceptionCheck):
     54        (JSC::DFG::JITCompiler::addFastExceptionCheck):
     55        * dfg/DFGOperations.cpp:
     56        * dfg/DFGRepatch.cpp:
     57        (JSC::DFG::dfgLinkFor):
     58        * dfg/DFGSpeculativeJIT.h:
     59        (JSC::DFG::SpeculativeJIT::appendCallWithExceptionCheck):
     60        * dfg/DFGSpeculativeJIT32_64.cpp:
     61        (JSC::DFG::SpeculativeJIT::emitCall):
     62        * dfg/DFGSpeculativeJIT64.cpp:
     63        (JSC::DFG::SpeculativeJIT::emitCall):
     64        * dfg/DFGThunks.cpp:
     65        (JSC::DFG::emitPointerValidation):
     66        (DFG):
     67        (JSC::DFG::throwExceptionFromCallSlowPathGenerator):
     68        (JSC::DFG::slowPathFor):
     69        (JSC::DFG::linkForThunkGenerator):
     70        (JSC::DFG::linkCallThunkGenerator):
     71        (JSC::DFG::linkConstructThunkGenerator):
     72        (JSC::DFG::virtualForThunkGenerator):
     73        (JSC::DFG::virtualCallThunkGenerator):
     74        (JSC::DFG::virtualConstructThunkGenerator):
     75        * dfg/DFGThunks.h:
     76        (DFG):
     77        * jit/JIT.cpp:
     78        (JSC::JIT::privateCompile):
     79        (JSC::JIT::linkFor):
     80        * runtime/Executable.h:
     81        (ExecutableBase):
     82        (JSC::ExecutableBase::offsetOfJITCodeFor):
     83        (JSC::ExecutableBase::offsetOfNumParametersFor):
     84        * runtime/JSValue.h:
     85        (JSValue):
     86
    1872012-07-11  Filip Pizlo  <fpizlo@apple.com>
    288
  • trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.cpp

    r104646 r122392  
    2828
    2929#include "DFGOperations.h"
     30#include "DFGThunks.h"
    3031#include "RepatchBuffer.h"
    3132
     
    3940    if (isDFG) {
    4041#if ENABLE(DFG_JIT)
    41         repatchBuffer.relink(CodeLocationCall(callReturnLocation), callType == Construct ? DFG::operationLinkConstruct : DFG::operationLinkCall);
     42        repatchBuffer.relink(callReturnLocation, (callType == Construct ? globalData.getCTIStub(DFG::linkConstructThunkGenerator) : globalData.getCTIStub(DFG::linkCallThunkGenerator)).code());
    4243#else
    4344        ASSERT_NOT_REACHED();
    4445#endif
    4546    } else
    46         repatchBuffer.relink(CodeLocationNearCall(callReturnLocation), callType == Construct ? globalData.jitStubs->ctiVirtualConstructLink() : globalData.jitStubs->ctiVirtualCallLink());
     47        repatchBuffer.relink(callReturnLocation, callType == Construct ? globalData.jitStubs->ctiVirtualConstructLink() : globalData.jitStubs->ctiVirtualCallLink());
    4748    hasSeenShouldRepatch = false;
    4849    callee.clear();
  • trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.h

    r106075 r122392  
    6666    }
    6767
    68     CodeLocationLabel callReturnLocation; // it's a near call in the old JIT, or a normal call in DFG
     68    CodeLocationNearCall callReturnLocation;
    6969    CodeLocationDataLabelPtr hotPathBegin;
    7070    CodeLocationNearCall hotPathOther;
  • trunk/Source/JavaScriptCore/bytecode/CodeOrigin.h

    r118136 r122392  
    4040
    4141struct CodeOrigin {
     42    static const unsigned maximumBytecodeIndex = (1u << 29) - 1;
     43   
    4244    // Bytecode offset that you'd use to re-execute this instruction.
    4345    unsigned bytecodeIndex : 29;
     
    4951   
    5052    CodeOrigin()
    51         : bytecodeIndex(std::numeric_limits<uint32_t>::max())
     53        : bytecodeIndex(maximumBytecodeIndex)
    5254        , valueProfileOffset(0)
    5355        , inlineCallFrame(0)
     
    6062        , inlineCallFrame(inlineCallFrame)
    6163    {
    62         ASSERT(bytecodeIndex < (1u << 29));
     64        ASSERT(bytecodeIndex <= maximumBytecodeIndex);
    6365        ASSERT(valueProfileOffset < (1u << 3));
    6466    }
    6567   
    66     bool isSet() const { return bytecodeIndex != std::numeric_limits<uint32_t>::max(); }
     68    bool isSet() const { return bytecodeIndex != maximumBytecodeIndex; }
    6769   
    6870    unsigned bytecodeIndexForValueProfile() const
  • trunk/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h

    r121885 r122392  
    4747        : m_globalData(globalData)
    4848        , m_codeBlock(codeBlock)
    49         , m_baselineCodeBlock(codeBlock->baselineVersion())
    50     {
    51         ASSERT(m_codeBlock);
    52         ASSERT(m_baselineCodeBlock);
    53         ASSERT(!m_baselineCodeBlock->alternative());
    54         ASSERT(m_baselineCodeBlock->getJITType() == JITCode::BaselineJIT);
     49        , m_baselineCodeBlock(codeBlock ? codeBlock->baselineVersion() : 0)
     50    {
     51        if (m_codeBlock) {
     52            ASSERT(m_baselineCodeBlock);
     53            ASSERT(!m_baselineCodeBlock->alternative());
     54            ASSERT(m_baselineCodeBlock->getJITType() == JITCode::BaselineJIT);
     55        }
    5556    }
    5657   
  • trunk/Source/JavaScriptCore/dfg/DFGCCallHelpers.h

    r121885 r122392  
    3838class CCallHelpers : public AssemblyHelpers {
    3939public:
    40     CCallHelpers(JSGlobalData* globalData, CodeBlock* codeBlock)
     40    CCallHelpers(JSGlobalData* globalData, CodeBlock* codeBlock = 0)
    4141        : AssemblyHelpers(globalData, codeBlock)
    4242    {
  • trunk/Source/JavaScriptCore/dfg/DFGGPRInfo.h

    r121885 r122392  
    274274    static const GPRReg nonArgGPR0 = X86Registers::eax; // regT0
    275275    static const GPRReg nonArgGPR1 = X86Registers::ebx; // regT3
     276    static const GPRReg nonArgGPR2 = X86Registers::esi; // regT4
    276277    static const GPRReg returnValueGPR = X86Registers::eax; // regT0
    277278    static const GPRReg returnValueGPR2 = X86Registers::edx; // regT1
     
    345346    static const GPRReg nonArgGPR0 = X86Registers::eax; // regT0
    346347    static const GPRReg nonArgGPR1 = X86Registers::ebx; // regT3
     348    static const GPRReg nonArgGPR2 = X86Registers::r10; // regT8
    347349    static const GPRReg returnValueGPR = X86Registers::eax; // regT0
    348350    static const GPRReg returnValueGPR2 = X86Registers::edx; // regT1
     
    417419    static const GPRReg nonArgGPR0 = ARMRegisters::r4; // regT3
    418420    static const GPRReg nonArgGPR1 = ARMRegisters::r8; // regT4
     421    static const GPRReg nonArgGPR2 = ARMRegisters::r9; // regT5
    419422    static const GPRReg returnValueGPR = ARMRegisters::r0; // regT0
    420423    static const GPRReg returnValueGPR2 = ARMRegisters::r1; // regT1
  • trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp

    r122206 r122392  
    154154        codeOrigins[i].codeOrigin = record.m_codeOrigin;
    155155        codeOrigins[i].callReturnOffset = returnAddressOffset;
    156         record.m_token.assertCodeOriginIndex(i);
    157156    }
    158157   
     
    190189        info.callType = m_jsCalls[i].m_callType;
    191190        info.isDFG = true;
    192         info.callReturnLocation = CodeLocationLabel(linkBuffer.locationOf(m_jsCalls[i].m_slowCall));
     191        linkBuffer.link(m_jsCalls[i].m_slowCall, FunctionPtr((m_globalData->getCTIStub(info.callType == CallLinkInfo::Construct ? linkConstructThunkGenerator : linkCallThunkGenerator)).code().executableAddress()));
     192        info.callReturnLocation = linkBuffer.locationOfNearCall(m_jsCalls[i].m_slowCall);
    193193        info.hotPathBegin = linkBuffer.locationOf(m_jsCalls[i].m_targetToCheck);
    194194        info.hotPathOther = linkBuffer.locationOfNearCall(m_jsCalls[i].m_fastCall);
     
    281281    poke(GPRInfo::callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
    282282
    283     CallBeginToken token = beginCall();
     283    CallBeginToken token;
     284    beginCall(CodeOrigin(0), token);
    284285    Call callRegisterFileCheck = call();
    285286    notifyCall(callRegisterFileCheck, CodeOrigin(0), token);
     
    298299    move(stackPointerRegister, GPRInfo::argumentGPR0);
    299300    poke(GPRInfo::callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
    300     token = beginCall();
     301    beginCall(CodeOrigin(0), token);
    301302    Call callArityCheck = call();
    302303    notifyCall(callArityCheck, CodeOrigin(0), token);
  • trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.h

    r121925 r122392  
    7777    CallBeginToken()
    7878#if !ASSERT_DISABLED
    79         : m_codeOriginIndex(UINT_MAX)
    80 #endif
    81     {
    82     }
    83    
    84     explicit CallBeginToken(unsigned codeOriginIndex)
     79        : m_registered(false)
     80        , m_exceptionCheckIndex(std::numeric_limits<unsigned>::max())
     81#endif
     82    {
     83    }
     84   
     85    ~CallBeginToken()
     86    {
     87        ASSERT(m_registered || !m_codeOrigin.isSet());
     88        ASSERT(m_codeOrigin.isSet() == (m_exceptionCheckIndex != std::numeric_limits<unsigned>::max()));
     89    }
     90   
     91    void set(CodeOrigin codeOrigin, unsigned index)
     92    {
    8593#if !ASSERT_DISABLED
    86         : m_codeOriginIndex(codeOriginIndex)
    87 #endif
    88     {
    89         UNUSED_PARAM(codeOriginIndex);
    90     }
    91    
    92     void assertCodeOriginIndex(unsigned codeOriginIndex) const
    93     {
    94         ASSERT_UNUSED(codeOriginIndex, codeOriginIndex < UINT_MAX);
    95         ASSERT_UNUSED(codeOriginIndex, codeOriginIndex == m_codeOriginIndex);
    96     }
    97 
     94        ASSERT(m_registered || !m_codeOrigin.isSet());
     95        ASSERT(m_codeOrigin.isSet() == (m_exceptionCheckIndex != std::numeric_limits<unsigned>::max()));
     96        m_codeOrigin = codeOrigin;
     97        m_registered = false;
     98        m_exceptionCheckIndex = index;
     99#else
     100        UNUSED_PARAM(codeOrigin);
     101        UNUSED_PARAM(index);
     102#endif
     103    }
     104   
     105    void registerWithExceptionCheck(CodeOrigin codeOrigin, unsigned index)
     106    {
     107#if !ASSERT_DISABLED
     108        ASSERT(m_codeOrigin == codeOrigin);
     109        if (m_registered)
     110            return;
     111        ASSERT(m_exceptionCheckIndex == index);
     112        m_registered = true;
     113#else
     114        UNUSED_PARAM(codeOrigin);
     115        UNUSED_PARAM(index);
     116#endif
     117    }
     118
     119#if !ASSERT_DISABLED
     120    const CodeOrigin& codeOrigin() const
     121    {
     122        return m_codeOrigin;
     123    }
     124#endif
     125   
    98126private:
    99127#if !ASSERT_DISABLED
    100     unsigned m_codeOriginIndex;
     128    CodeOrigin m_codeOrigin;
     129    bool m_registered;
     130    unsigned m_exceptionCheckIndex;
    101131#endif
    102132};
     
    108138// (unset if not present) and code origin used to recover handler/source info.
    109139struct CallExceptionRecord {
    110     CallExceptionRecord(MacroAssembler::Call call, CodeOrigin codeOrigin, CallBeginToken token)
     140    CallExceptionRecord(MacroAssembler::Call call, CodeOrigin codeOrigin)
    111141        : m_call(call)
    112142        , m_codeOrigin(codeOrigin)
    113         , m_token(token)
    114     {
    115     }
    116 
    117     CallExceptionRecord(MacroAssembler::Call call, MacroAssembler::Jump exceptionCheck, CodeOrigin codeOrigin, CallBeginToken token)
     143    {
     144    }
     145
     146    CallExceptionRecord(MacroAssembler::Call call, MacroAssembler::Jump exceptionCheck, CodeOrigin codeOrigin)
    118147        : m_call(call)
    119148        , m_exceptionCheck(exceptionCheck)
    120149        , m_codeOrigin(codeOrigin)
    121         , m_token(token)
    122150    {
    123151    }
     
    126154    MacroAssembler::Jump m_exceptionCheck;
    127155    CodeOrigin m_codeOrigin;
    128     CallBeginToken m_token;
    129156};
    130157
     
    258285    }
    259286   
     287    unsigned currentCodeOriginIndex() const
     288    {
     289        return m_currentCodeOriginIndex;
     290    }
     291   
    260292    // Get a token for beginning a call, and set the current code origin index in
    261     // the call frame.
    262     CallBeginToken beginCall()
    263     {
    264         unsigned codeOriginIndex = m_currentCodeOriginIndex++;
    265         store32(TrustedImm32(codeOriginIndex), tagFor(static_cast<VirtualRegister>(RegisterFile::ArgumentCount)));
    266         return CallBeginToken(codeOriginIndex);
     293    // the call frame. For each beginCall() there must be at least one exception
     294    // check, and all of the exception checks must have the same CodeOrigin as the
     295    // beginCall().
     296    void beginCall(CodeOrigin codeOrigin, CallBeginToken& token)
     297    {
     298        unsigned index = m_exceptionChecks.size();
     299        store32(TrustedImm32(index), tagFor(static_cast<VirtualRegister>(RegisterFile::ArgumentCount)));
     300        token.set(codeOrigin, index);
    267301    }
    268302
    269303    // Notify the JIT of a call that does not require linking.
    270     void notifyCall(Call functionCall, CodeOrigin codeOrigin, CallBeginToken token)
    271     {
    272         m_exceptionChecks.append(CallExceptionRecord(functionCall, codeOrigin, token));
     304    void notifyCall(Call functionCall, CodeOrigin codeOrigin, CallBeginToken& token)
     305    {
     306        token.registerWithExceptionCheck(codeOrigin, m_exceptionChecks.size());
     307        m_exceptionChecks.append(CallExceptionRecord(functionCall, codeOrigin));
    273308    }
    274309
     
    280315        return functionCall;
    281316    }
     317   
     318    void prepareForExceptionCheck()
     319    {
     320        move(TrustedImm32(m_exceptionChecks.size()), GPRInfo::nonPreservedNonReturnGPR);
     321    }
    282322
    283323    // Add a call out from JIT code, with an exception check.
    284     void addExceptionCheck(Call functionCall, CodeOrigin codeOrigin, CallBeginToken token)
    285     {
    286         move(TrustedImm32(m_exceptionChecks.size()), GPRInfo::nonPreservedNonReturnGPR);
    287         m_exceptionChecks.append(CallExceptionRecord(functionCall, emitExceptionCheck(), codeOrigin, token));
     324    void addExceptionCheck(Call functionCall, CodeOrigin codeOrigin, CallBeginToken& token)
     325    {
     326        prepareForExceptionCheck();
     327        token.registerWithExceptionCheck(codeOrigin, m_exceptionChecks.size());
     328        m_exceptionChecks.append(CallExceptionRecord(functionCall, emitExceptionCheck(), codeOrigin));
    288329    }
    289330   
    290331    // Add a call out from JIT code, with a fast exception check that tests if the return value is zero.
    291     void addFastExceptionCheck(Call functionCall, CodeOrigin codeOrigin, CallBeginToken token)
    292     {
    293         move(TrustedImm32(m_exceptionChecks.size()), GPRInfo::nonPreservedNonReturnGPR);
     332    void addFastExceptionCheck(Call functionCall, CodeOrigin codeOrigin, CallBeginToken& token)
     333    {
     334        prepareForExceptionCheck();
    294335        Jump exceptionCheck = branchTestPtr(Zero, GPRInfo::returnValueGPR);
    295         m_exceptionChecks.append(CallExceptionRecord(functionCall, exceptionCheck, codeOrigin, token));
     336        token.registerWithExceptionCheck(codeOrigin, m_exceptionChecks.size());
     337        m_exceptionChecks.append(CallExceptionRecord(functionCall, exceptionCheck, codeOrigin));
    296338    }
    297339   
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r122206 r122392  
    3131#include "DFGOSRExit.h"
    3232#include "DFGRepatch.h"
     33#include "DFGThunks.h"
    3334#include "HostCallReturnValue.h"
    3435#include "GetterSetter.h"
     
    850851    execCallee->setScopeChain(exec->scopeChain());
    851852    execCallee->setCodeBlock(0);
    852     execCallee->clearReturnPC();
    853853
    854854    if (kind == CodeForCall) {
     
    863863            globalData->hostCallReturnValue = JSValue::decode(callData.native.function(execCallee));
    864864            if (globalData->exception)
    865                 return 0;
     865                return globalData->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress();
    866866
    867867            return reinterpret_cast<void*>(getHostCallReturnValue);
     
    870870        ASSERT(callType == CallTypeNone);
    871871        exec->globalData().exception = createNotAFunctionError(exec, callee);
    872         return 0;
     872        return globalData->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress();
    873873    }
    874874
     
    885885        globalData->hostCallReturnValue = JSValue::decode(constructData.native.function(execCallee));
    886886        if (globalData->exception)
    887             return 0;
     887            return globalData->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress();
    888888
    889889        return reinterpret_cast<void*>(getHostCallReturnValue);
     
    892892    ASSERT(constructType == ConstructTypeNone);
    893893    exec->globalData().exception = createNotAConstructorError(exec, callee);
    894     return 0;
    895 }
    896 
    897 inline void* linkFor(ExecState* execCallee, ReturnAddressPtr returnAddress, CodeSpecializationKind kind)
     894    return globalData->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress();
     895}
     896
     897inline void* linkFor(ExecState* execCallee, CodeSpecializationKind kind)
    898898{
    899899    ExecState* exec = execCallee->callerFrame();
     
    919919        if (error) {
    920920            globalData->exception = createStackOverflowError(exec);
    921             return 0;
     921            return globalData->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress();
    922922        }
    923923        codeBlock = &functionExecutable->generatedBytecodeFor(kind);
     
    927927            codePtr = functionExecutable->generatedJITCodeFor(kind).addressForCall();
    928928    }
    929     CallLinkInfo& callLinkInfo = exec->codeBlock()->getCallLinkInfo(returnAddress);
     929    CallLinkInfo& callLinkInfo = exec->codeBlock()->getCallLinkInfo(execCallee->returnPC());
    930930    if (!callLinkInfo.seenOnce())
    931931        callLinkInfo.setSeen();
     
    935935}
    936936
    937 P_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_E(operationLinkCall);
    938 void* DFG_OPERATION operationLinkCallWithReturnAddress(ExecState* execCallee, ReturnAddressPtr returnAddress)
    939 {
    940     return linkFor(execCallee, returnAddress, CodeForCall);
    941 }
    942 
    943 P_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_E(operationLinkConstruct);
    944 void* DFG_OPERATION operationLinkConstructWithReturnAddress(ExecState* execCallee, ReturnAddressPtr returnAddress)
    945 {
    946     return linkFor(execCallee, returnAddress, CodeForConstruct);
     937void* DFG_OPERATION operationLinkCall(ExecState* execCallee)
     938{
     939    return linkFor(execCallee, CodeForCall);
     940}
     941
     942void* DFG_OPERATION operationLinkConstruct(ExecState* execCallee)
     943{
     944    return linkFor(execCallee, CodeForConstruct);
    947945}
    948946
     
    966964        if (error) {
    967965            exec->globalData().exception = error;
    968             return 0;
     966            return globalData->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress();
    969967        }
    970968    }
  • trunk/Source/JavaScriptCore/dfg/DFGRepatch.cpp

    r122166 r122392  
    3131#include "DFGCCallHelpers.h"
    3232#include "DFGSpeculativeJIT.h"
     33#include "DFGThunks.h"
    3334#include "GCAwareJITStubRoutine.h"
    3435#include "LinkBuffer.h"
     
    917918{
    918919    CodeBlock* callerCodeBlock = exec->callerFrame()->codeBlock();
     920    JSGlobalData* globalData = callerCodeBlock->globalData();
    919921   
    920922    RepatchBuffer repatchBuffer(callerCodeBlock);
     
    929931   
    930932    if (kind == CodeForCall) {
    931         repatchBuffer.relink(CodeLocationCall(callLinkInfo.callReturnLocation), operationVirtualCall);
     933        repatchBuffer.relink(callLinkInfo.callReturnLocation, globalData->getCTIStub(virtualCallThunkGenerator).code());
    932934        return;
    933935    }
    934936    ASSERT(kind == CodeForConstruct);
    935     repatchBuffer.relink(CodeLocationCall(callLinkInfo.callReturnLocation), operationVirtualConstruct);
     937    repatchBuffer.relink(callLinkInfo.callReturnLocation, globalData->getCTIStub(virtualConstructThunkGenerator).code());
    936938}
    937939
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r122385 r122392  
    17391739        prepareForExternalCall();
    17401740        CodeOrigin codeOrigin = at(m_compileIndex).codeOrigin;
    1741         CallBeginToken token = m_jit.beginCall();
     1741        CallBeginToken token;
     1742        m_jit.beginCall(codeOrigin, token);
    17421743        JITCompiler::Call call = m_jit.appendCall(function);
    17431744        m_jit.addExceptionCheck(call, codeOrigin, token);
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r121946 r122392  
    10081008    JITCompiler::JumpList slowPath;
    10091009
     1010    CallBeginToken token;
     1011    m_jit.beginCall(node.codeOrigin, token);
     1012   
     1013    m_jit.addPtr(TrustedImm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister);
     1014   
    10101015    slowPath.append(m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleePayloadGPR, targetToCheck));
    10111016    slowPath.append(m_jit.branch32(MacroAssembler::NotEqual, calleeTagGPR, TrustedImm32(JSValue::CellTag)));
    10121017    m_jit.loadPtr(MacroAssembler::Address(calleePayloadGPR, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), resultPayloadGPR);
    1013     m_jit.storePtr(resultPayloadGPR, callFramePayloadSlot(RegisterFile::ScopeChain));
    1014     m_jit.store32(MacroAssembler::TrustedImm32(JSValue::CellTag), callFrameTagSlot(RegisterFile::ScopeChain));
    1015 
    1016     m_jit.addPtr(TrustedImm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister);
     1018    m_jit.storePtr(resultPayloadGPR, MacroAssembler::Address(GPRInfo::callFrameRegister, static_cast<ptrdiff_t>(sizeof(Register)) * RegisterFile::ScopeChain + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)));
     1019    m_jit.store32(MacroAssembler::TrustedImm32(JSValue::CellTag), MacroAssembler::Address(GPRInfo::callFrameRegister, static_cast<ptrdiff_t>(sizeof(Register)) * RegisterFile::ScopeChain + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)));
    10171020
    10181021    CodeOrigin codeOrigin = at(m_compileIndex).codeOrigin;
    1019     CallBeginToken token = m_jit.beginCall();
    10201022    JITCompiler::Call fastCall = m_jit.nearCall();
    10211023    m_jit.notifyCall(fastCall, codeOrigin, token);
     
    10251027    slowPath.link(&m_jit);
    10261028
    1027     m_jit.addPtr(TrustedImm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
    1028     m_jit.poke(GPRInfo::argumentGPR0);
    1029     token = m_jit.beginCall();
    1030     JITCompiler::Call slowCall = m_jit.appendCall(slowCallFunction);
    1031     m_jit.addFastExceptionCheck(slowCall, codeOrigin, token);
    1032     m_jit.addPtr(TrustedImm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister);
    1033     token = m_jit.beginCall();
    1034     JITCompiler::Call theCall = m_jit.call(GPRInfo::returnValueGPR);
    1035     m_jit.notifyCall(theCall, codeOrigin, token);
     1029    if (calleeTagGPR == GPRInfo::nonArgGPR0) {
     1030        if (calleePayloadGPR == GPRInfo::nonArgGPR1)
     1031            m_jit.swap(GPRInfo::nonArgGPR1, GPRInfo::nonArgGPR0);
     1032        else {
     1033            m_jit.move(calleeTagGPR, GPRInfo::nonArgGPR1);
     1034            m_jit.move(calleePayloadGPR, GPRInfo::nonArgGPR0);
     1035        }
     1036    } else {
     1037        m_jit.move(calleePayloadGPR, GPRInfo::nonArgGPR0);
     1038        m_jit.move(calleeTagGPR, GPRInfo::nonArgGPR1);
     1039    }
     1040    m_jit.prepareForExceptionCheck();
     1041    JITCompiler::Call slowCall = m_jit.nearCall();
     1042    m_jit.notifyCall(slowCall, codeOrigin, token);
    10361043
    10371044    done.link(&m_jit);
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r121925 r122392  
    999999    JITCompiler::Jump slowPath;
    10001000
     1001    CallBeginToken token;
     1002    m_jit.beginCall(node.codeOrigin, token);
     1003   
     1004    m_jit.addPtr(TrustedImm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister);
     1005   
    10011006    slowPath = m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleeGPR, targetToCheck, MacroAssembler::TrustedImmPtr(JSValue::encode(JSValue())));
    10021007    m_jit.loadPtr(MacroAssembler::Address(calleeGPR, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), resultGPR);
    1003     m_jit.storePtr(resultGPR, callFrameSlot(RegisterFile::ScopeChain));
    1004 
    1005     m_jit.addPtr(TrustedImm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister);
    1006    
     1008    m_jit.storePtr(resultGPR, MacroAssembler::Address(GPRInfo::callFrameRegister, static_cast<ptrdiff_t>(sizeof(Register)) * RegisterFile::ScopeChain));
     1009
    10071010    CodeOrigin codeOrigin = at(m_compileIndex).codeOrigin;
    1008     CallBeginToken token = m_jit.beginCall();
    10091011    JITCompiler::Call fastCall = m_jit.nearCall();
    10101012    m_jit.notifyCall(fastCall, codeOrigin, token);
     
    10141016    slowPath.link(&m_jit);
    10151017   
    1016     m_jit.addPtr(TrustedImm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
    1017     token = m_jit.beginCall();
    1018     JITCompiler::Call slowCall = m_jit.appendCall(slowCallFunction);
    1019     m_jit.addFastExceptionCheck(slowCall, codeOrigin, token);
    1020     m_jit.addPtr(TrustedImm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister);
    1021     token = m_jit.beginCall();
    1022     JITCompiler::Call theCall = m_jit.call(GPRInfo::returnValueGPR);
    1023     m_jit.notifyCall(theCall, codeOrigin, token);
     1018    m_jit.move(calleeGPR, GPRInfo::nonArgGPR0);
     1019    m_jit.prepareForExceptionCheck();
     1020    JITCompiler::Call slowCall = m_jit.nearCall();
     1021    m_jit.notifyCall(slowCall, codeOrigin, token);
    10241022   
    10251023    done.link(&m_jit);
  • trunk/Source/JavaScriptCore/dfg/DFGThunks.cpp

    r120786 r122392  
    2929#if ENABLE(DFG_JIT)
    3030
     31#include "DFGCCallHelpers.h"
    3132#include "DFGFPRInfo.h"
    3233#include "DFGGPRInfo.h"
     
    8384}
    8485
     86inline void emitPointerValidation(CCallHelpers& jit, GPRReg pointerGPR)
     87{
     88#if !ASSERT_DISABLED
     89    CCallHelpers::Jump isNonZero = jit.branchTestPtr(CCallHelpers::NonZero, pointerGPR);
     90    jit.breakpoint();
     91    isNonZero.link(&jit);
     92    jit.push(pointerGPR);
     93    jit.load8(pointerGPR, pointerGPR);
     94    jit.pop(pointerGPR);
     95#else
     96    UNUSED_PARAM(jit);
     97    UNUSED_PARAM(pointerGPR);
     98#endif
     99}
     100
     101MacroAssemblerCodeRef throwExceptionFromCallSlowPathGenerator(JSGlobalData* globalData)
     102{
     103    CCallHelpers jit(globalData);
     104   
     105    // We will jump to here if the JIT code thinks it's making a call, but the
     106    // linking helper (C++ code) decided to throw an exception instead. We will
     107    // have saved the callReturnIndex in the first arguments of JITStackFrame.
     108    // Note that the return address will be on the stack at this point, so we
     109    // need to remove it and drop it on the floor, since we don't care about it.
     110    // Finally note that the call frame register points at the callee frame, so
     111    // we need to pop it.
     112    jit.preserveReturnAddressAfterCall(GPRInfo::nonPreservedNonReturnGPR);
     113    jit.loadPtr(
     114        CCallHelpers::Address(
     115            GPRInfo::callFrameRegister,
     116            static_cast<ptrdiff_t>(sizeof(Register)) * RegisterFile::CallerFrame),
     117        GPRInfo::callFrameRegister);
     118    jit.peek(GPRInfo::nonPreservedNonReturnGPR, JITSTACKFRAME_ARGS_INDEX);
     119    jit.setupArgumentsWithExecState(GPRInfo::nonPreservedNonReturnGPR);
     120    jit.move(CCallHelpers::TrustedImmPtr(bitwise_cast<void*>(lookupExceptionHandler)), GPRInfo::nonArgGPR0);
     121    emitPointerValidation(jit, GPRInfo::nonArgGPR0);
     122    jit.call(GPRInfo::nonArgGPR0);
     123    emitPointerValidation(jit, GPRInfo::returnValueGPR2);
     124    jit.jump(GPRInfo::returnValueGPR2);
     125   
     126    LinkBuffer patchBuffer(*globalData, &jit, GLOBAL_THUNK_ID);
     127    return FINALIZE_CODE(patchBuffer, ("DFG throw exception from call slow path thunk"));
     128}
     129
     130static void slowPathFor(
     131    CCallHelpers& jit, JSGlobalData* globalData, P_DFGOperation_E slowPathFunction)
     132{
     133    jit.preserveReturnAddressAfterCall(GPRInfo::nonArgGPR2);
     134    emitPointerValidation(jit, GPRInfo::nonArgGPR2);
     135    jit.storePtr(
     136        GPRInfo::nonArgGPR2,
     137        CCallHelpers::Address(
     138            GPRInfo::callFrameRegister,
     139            static_cast<ptrdiff_t>(sizeof(Register)) * RegisterFile::ReturnPC));
     140    jit.storePtr(GPRInfo::callFrameRegister, &globalData->topCallFrame);
     141    jit.poke(GPRInfo::nonPreservedNonReturnGPR, JITSTACKFRAME_ARGS_INDEX);
     142    jit.setupArgumentsExecState();
     143    jit.move(CCallHelpers::TrustedImmPtr(bitwise_cast<void*>(slowPathFunction)), GPRInfo::nonArgGPR0);
     144    emitPointerValidation(jit, GPRInfo::nonArgGPR0);
     145    jit.call(GPRInfo::nonArgGPR0);
     146   
     147    // This slow call will return the address of one of the following:
     148    // 1) Exception throwing thunk.
     149    // 2) Host call return value returner thingy.
     150    // 3) The function to call.
     151    jit.loadPtr(
     152        CCallHelpers::Address(
     153            GPRInfo::callFrameRegister,
     154            static_cast<ptrdiff_t>(sizeof(Register)) * RegisterFile::ReturnPC),
     155        GPRInfo::nonPreservedNonReturnGPR);
     156    jit.storePtr(
     157        CCallHelpers::TrustedImmPtr(0),
     158        CCallHelpers::Address(
     159            GPRInfo::callFrameRegister,
     160            static_cast<ptrdiff_t>(sizeof(Register)) * RegisterFile::ReturnPC));
     161    emitPointerValidation(jit, GPRInfo::nonPreservedNonReturnGPR);
     162    jit.restoreReturnAddressBeforeReturn(GPRInfo::nonPreservedNonReturnGPR);
     163    emitPointerValidation(jit, GPRInfo::returnValueGPR);
     164    jit.jump(GPRInfo::returnValueGPR);
     165}
     166
     167static MacroAssemblerCodeRef linkForThunkGenerator(
     168    JSGlobalData* globalData, CodeSpecializationKind kind)
     169{
     170    // The return address is on the stack or in the link register. We will hence
     171    // save the return address to the call frame while we make a C++ function call
     172    // to perform linking and lazy compilation if necessary. We expect the callee
     173    // to be in nonArgGPR0/nonArgGPR1 (payload/tag), the call frame to have already
     174    // been adjusted, nonPreservedNonReturnGPR holds the exception handler index,
     175    // and all other registers to be available for use. We use JITStackFrame::args
     176    // to save important information across calls.
     177   
     178    CCallHelpers jit(globalData);
     179   
     180    slowPathFor(jit, globalData, kind == CodeForCall ? operationLinkCall : operationLinkConstruct);
     181   
     182    LinkBuffer patchBuffer(*globalData, &jit, GLOBAL_THUNK_ID);
     183    return FINALIZE_CODE(
     184        patchBuffer,
     185        ("DFG link %s slow path thunk", kind == CodeForCall ? "call" : "construct"));
     186}
     187
     188MacroAssemblerCodeRef linkCallThunkGenerator(JSGlobalData* globalData)
     189{
     190    return linkForThunkGenerator(globalData, CodeForCall);
     191}
     192
     193MacroAssemblerCodeRef linkConstructThunkGenerator(JSGlobalData* globalData)
     194{
     195    return linkForThunkGenerator(globalData, CodeForConstruct);
     196}
     197
     198static MacroAssemblerCodeRef virtualForThunkGenerator(
     199    JSGlobalData* globalData, CodeSpecializationKind kind)
     200{
     201    // The return address is on the stack, or in the link register. We will hence
     202    // jump to the callee, or save the return address to the call frame while we
     203    // make a C++ function call to the appropriate DFG operation.
     204
     205    CCallHelpers jit(globalData);
     206   
     207    CCallHelpers::JumpList slowCase;
     208
     209    // FIXME: we should have a story for eliminating these checks. In many cases,
     210    // the DFG knows that the value is definitely a cell, or definitely a function.
     211   
     212#if USE(JSVALUE64)
     213    slowCase.append(
     214        jit.branchTestPtr(
     215            CCallHelpers::NonZero, GPRInfo::nonArgGPR0, GPRInfo::tagMaskRegister));
     216#else
     217    slowCase.append(
     218        jit.branch32(
     219            CCallHelpers::NotEqual, GPRInfo::nonArgGPR1,
     220            CCallHelpers::TrustedImm32(JSValue::CellTag)));
     221#endif
     222    slowCase.append(
     223        jit.branchPtr(
     224            CCallHelpers::NotEqual,
     225            CCallHelpers::Address(GPRInfo::nonArgGPR0, JSCell::classInfoOffset()),
     226            CCallHelpers::TrustedImmPtr(&JSFunction::s_info)));
     227   
     228    // Now we know we have a JSFunction.
     229   
     230    jit.loadPtr(
     231        CCallHelpers::Address(GPRInfo::nonArgGPR0, JSFunction::offsetOfExecutable()),
     232        GPRInfo::nonArgGPR2);
     233    slowCase.append(
     234        jit.branch32(
     235            CCallHelpers::LessThan,
     236            CCallHelpers::Address(
     237                GPRInfo::nonArgGPR2, ExecutableBase::offsetOfNumParametersFor(kind)),
     238            CCallHelpers::TrustedImm32(0)));
     239   
     240    // Now we know that we have a CodeBlock, and we're committed to making a fast
     241    // call.
     242   
     243    jit.loadPtr(
     244        CCallHelpers::Address(GPRInfo::nonArgGPR0, JSFunction::offsetOfScopeChain()),
     245        GPRInfo::nonArgGPR1);
     246#if USE(JSVALUE64)
     247    jit.storePtr(
     248        GPRInfo::nonArgGPR1,
     249        CCallHelpers::Address(
     250            GPRInfo::callFrameRegister,
     251            static_cast<ptrdiff_t>(sizeof(Register)) * RegisterFile::ScopeChain));
     252#else
     253    jit.storePtr(
     254        GPRInfo::nonArgGPR1,
     255        CCallHelpers::Address(
     256            GPRInfo::callFrameRegister,
     257            static_cast<ptrdiff_t>(sizeof(Register)) * RegisterFile::ScopeChain +
     258            OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)));
     259    jit.store32(
     260        CCallHelpers::TrustedImm32(JSValue::CellTag),
     261        CCallHelpers::Address(
     262            GPRInfo::callFrameRegister,
     263            static_cast<ptrdiff_t>(sizeof(Register)) * RegisterFile::ScopeChain +
     264            OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)));
     265#endif
     266   
     267    jit.loadPtr(
     268        CCallHelpers::Address(GPRInfo::nonArgGPR2, ExecutableBase::offsetOfJITCodeWithArityCheckFor(kind)),
     269        GPRInfo::regT0);
     270   
     271    // Make a tail call. This will return back to DFG code.
     272    emitPointerValidation(jit, GPRInfo::regT0);
     273    jit.jump(GPRInfo::regT0);
     274
     275    slowCase.link(&jit);
     276   
     277    // Here we don't know anything, so revert to the full slow path.
     278   
     279    slowPathFor(jit, globalData, kind == CodeForCall ? operationVirtualCall : operationVirtualConstruct);
     280   
     281    LinkBuffer patchBuffer(*globalData, &jit, GLOBAL_THUNK_ID);
     282    return FINALIZE_CODE(
     283        patchBuffer,
     284        ("DFG virtual %s slow path thunk", kind == CodeForCall ? "call" : "construct"));
     285}
     286
     287MacroAssemblerCodeRef virtualCallThunkGenerator(JSGlobalData* globalData)
     288{
     289    return virtualForThunkGenerator(globalData, CodeForCall);
     290}
     291
     292MacroAssemblerCodeRef virtualConstructThunkGenerator(JSGlobalData* globalData)
     293{
     294    return virtualForThunkGenerator(globalData, CodeForConstruct);
     295}
     296
    85297} } // namespace JSC::DFG
    86298
  • trunk/Source/JavaScriptCore/dfg/DFGThunks.h

    r99787 r122392  
    4141MacroAssemblerCodeRef osrExitGenerationThunkGenerator(JSGlobalData*);
    4242
     43MacroAssemblerCodeRef throwExceptionFromCallSlowPathGenerator(JSGlobalData*);
     44
     45MacroAssemblerCodeRef linkCallThunkGenerator(JSGlobalData*);
     46MacroAssemblerCodeRef linkConstructThunkGenerator(JSGlobalData*);
     47
     48MacroAssemblerCodeRef virtualCallThunkGenerator(JSGlobalData*);
     49MacroAssemblerCodeRef virtualConstructThunkGenerator(JSGlobalData*);
     50
    4351} } // namespace JSC::DFG
    4452
  • trunk/Source/JavaScriptCore/jit/JIT.cpp

    r121925 r122392  
    740740        info.callType = m_callStructureStubCompilationInfo[i].callType;
    741741        info.bytecodeIndex = m_callStructureStubCompilationInfo[i].bytecodeIndex;
    742         info.callReturnLocation = CodeLocationLabel(patchBuffer.locationOfNearCall(m_callStructureStubCompilationInfo[i].callReturnLocation));
     742        info.callReturnLocation = patchBuffer.locationOfNearCall(m_callStructureStubCompilationInfo[i].callReturnLocation);
    743743        info.hotPathBegin = patchBuffer.locationOf(m_callStructureStubCompilationInfo[i].hotPathBegin);
    744744        info.hotPathOther = patchBuffer.locationOfNearCall(m_callStructureStubCompilationInfo[i].hotPathOther);
     
    803803    // Patch the slow patch so we do not continue to try to link.
    804804    if (kind == CodeForCall) {
    805         repatchBuffer.relink(CodeLocationNearCall(callLinkInfo->callReturnLocation), globalData->jitStubs->ctiVirtualCall());
     805        repatchBuffer.relink(callLinkInfo->callReturnLocation, globalData->jitStubs->ctiVirtualCall());
    806806        return;
    807807    }
    808808
    809809    ASSERT(kind == CodeForConstruct);
    810     repatchBuffer.relink(CodeLocationNearCall(callLinkInfo->callReturnLocation), globalData->jitStubs->ctiVirtualConstruct());
     810    repatchBuffer.relink(callLinkInfo->callReturnLocation, globalData->jitStubs->ctiVirtualConstruct());
    811811}
    812812
  • trunk/Source/JavaScriptCore/runtime/Executable.h

    r119926 r122392  
    177177            return NoIntrinsic;
    178178        }
     179       
     180        static ptrdiff_t offsetOfJITCodeFor(CodeSpecializationKind kind)
     181        {
     182            if (kind == CodeForCall)
     183                return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForCall);
     184            ASSERT(kind == CodeForConstruct);
     185            return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForConstruct);
     186        }
     187       
     188        static ptrdiff_t offsetOfJITCodeWithArityCheckFor(CodeSpecializationKind kind)
     189        {
     190            if (kind == CodeForCall)
     191                return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForCallWithArityCheck);
     192            ASSERT(kind == CodeForConstruct);
     193            return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForConstructWithArityCheck);
     194        }
     195       
     196        static ptrdiff_t offsetOfNumParametersFor(CodeSpecializationKind kind)
     197        {
     198            if (kind == CodeForCall)
     199                return OBJECT_OFFSETOF(ExecutableBase, m_numParametersForCall);
     200            ASSERT(kind == CodeForConstruct);
     201            return OBJECT_OFFSETOF(ExecutableBase, m_numParametersForConstruct);
     202        }
    179203#endif
    180204
  • trunk/Source/JavaScriptCore/runtime/JSValue.h

    r118555 r122392  
    125125
    126126    public:
     127#if USE(JSVALUE32_64)
     128        enum { Int32Tag =        0xffffffff };
     129        enum { BooleanTag =      0xfffffffe };
     130        enum { NullTag =         0xfffffffd };
     131        enum { UndefinedTag =    0xfffffffc };
     132        enum { CellTag =         0xfffffffb };
     133        enum { EmptyValueTag =   0xfffffffa };
     134        enum { DeletedValueTag = 0xfffffff9 };
     135
     136        enum { LowestTag =  DeletedValueTag };
     137#endif
     138
    127139        static EncodedJSValue encode(JSValue);
    128140        static JSValue decode(EncodedJSValue);
     
    279291         * integer or boolean value; in the case of all other tags the payload is 0.
    280292         */
    281         enum { Int32Tag =        0xffffffff };
    282         enum { BooleanTag =      0xfffffffe };
    283         enum { NullTag =         0xfffffffd };
    284         enum { UndefinedTag =    0xfffffffc };
    285         enum { CellTag =         0xfffffffb };
    286         enum { EmptyValueTag =   0xfffffffa };
    287         enum { DeletedValueTag = 0xfffffff9 };
    288 
    289         enum { LowestTag =  DeletedValueTag };
    290 
    291293        uint32_t tag() const;
    292294        int32_t payload() const;
Note: See TracChangeset for help on using the changeset viewer.