JavaScriptCore/jit/JITStubCall.h
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2  * Copyright (C) 2008 Apple Inc. All rights reserved.
       
     3  *
       
     4  * Redistribution and use in source and binary forms, with or without
       
     5  * modification, are permitted provided that the following conditions
       
     6  * are met:
       
     7  * 1. Redistributions of source code must retain the above copyright
       
     8  *    notice, this list of conditions and the following disclaimer.
       
     9  * 2. Redistributions in binary form must reproduce the above copyright
       
    10  *    notice, this list of conditions and the following disclaimer in the
       
    11  *    documentation and/or other materials provided with the distribution.
       
    12  *
       
    13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
       
    14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
       
    15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
       
    16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
       
    17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
       
    18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
       
    19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
       
    20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
       
    21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
       
    22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
       
    23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
       
    24  */
       
    25 
       
    26 #ifndef JITStubCall_h
       
    27 #define JITStubCall_h
       
    28 
       
    29 #include "MacroAssemblerCodeRef.h"
       
    30 
       
    31 #if ENABLE(JIT)
       
    32 
       
    33 namespace JSC {
       
    34 
       
    35     class JITStubCall {
       
    36     public:
       
    37         JITStubCall(JIT* jit, JSObject* (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
       
    38             : m_jit(jit)
       
    39             , m_stub(stub)
       
    40             , m_returnType(Cell)
       
    41             , m_stackIndex(JITSTACKFRAME_ARGS_INDEX)
       
    42         {
       
    43         }
       
    44 
       
    45         JITStubCall(JIT* jit, JSPropertyNameIterator* (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
       
    46             : m_jit(jit)
       
    47             , m_stub(stub)
       
    48             , m_returnType(Cell)
       
    49             , m_stackIndex(JITSTACKFRAME_ARGS_INDEX)
       
    50         {
       
    51         }
       
    52 
       
    53         JITStubCall(JIT* jit, void* (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
       
    54             : m_jit(jit)
       
    55             , m_stub(stub)
       
    56             , m_returnType(VoidPtr)
       
    57             , m_stackIndex(JITSTACKFRAME_ARGS_INDEX)
       
    58         {
       
    59         }
       
    60 
       
    61         JITStubCall(JIT* jit, int (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
       
    62             : m_jit(jit)
       
    63             , m_stub(stub)
       
    64             , m_returnType(Int)
       
    65             , m_stackIndex(JITSTACKFRAME_ARGS_INDEX)
       
    66         {
       
    67         }
       
    68 
       
    69         JITStubCall(JIT* jit, bool (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
       
    70             : m_jit(jit)
       
    71             , m_stub(stub)
       
    72             , m_returnType(Int)
       
    73             , m_stackIndex(JITSTACKFRAME_ARGS_INDEX)
       
    74         {
       
    75         }
       
    76 
       
    77         JITStubCall(JIT* jit, void (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
       
    78             : m_jit(jit)
       
    79             , m_stub(stub)
       
    80             , m_returnType(Void)
       
    81             , m_stackIndex(JITSTACKFRAME_ARGS_INDEX)
       
    82         {
       
    83         }
       
    84 
       
    85 #if USE(JSVALUE32_64)
       
    86         JITStubCall(JIT* jit, EncodedJSValue (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
       
    87             : m_jit(jit)
       
    88             , m_stub(stub)
       
    89             , m_returnType(Value)
       
    90             , m_stackIndex(JITSTACKFRAME_ARGS_INDEX)
       
    91         {
       
    92         }
       
    93 #endif
       
    94 
       
    95         // Arguments are added first to last.
       
    96 
       
    97         void skipArgument()
       
    98         {
       
    99             m_stackIndex += stackIndexStep;
       
   100         }
       
   101 
       
   102         void addArgument(JIT::Imm32 argument)
       
   103         {
       
   104             m_jit->poke(argument, m_stackIndex);
       
   105             m_stackIndex += stackIndexStep;
       
   106         }
       
   107 
       
   108         void addArgument(JIT::ImmPtr argument)
       
   109         {
       
   110             m_jit->poke(argument, m_stackIndex);
       
   111             m_stackIndex += stackIndexStep;
       
   112         }
       
   113 
       
   114         void addArgument(JIT::RegisterID argument)
       
   115         {
       
   116             m_jit->poke(argument, m_stackIndex);
       
   117             m_stackIndex += stackIndexStep;
       
   118         }
       
   119         
       
   120 #if USE(JSVALUE32_64)
       
   121         void addArgument(const JSValue& value)
       
   122         {
       
   123             m_jit->poke(JIT::Imm32(value.payload()), m_stackIndex);
       
   124             m_jit->poke(JIT::Imm32(value.tag()), m_stackIndex + 1);
       
   125             m_stackIndex += stackIndexStep;
       
   126         }
       
   127 #endif
       
   128 
       
   129         void addArgument(JIT::RegisterID tag, JIT::RegisterID payload)
       
   130         {
       
   131             m_jit->poke(payload, m_stackIndex);
       
   132             m_jit->poke(tag, m_stackIndex + 1);
       
   133             m_stackIndex += stackIndexStep;
       
   134         }
       
   135 
       
   136 #if USE(JSVALUE32_64)
       
   137         void addArgument(unsigned srcVirtualRegister)
       
   138         {
       
   139             if (m_jit->m_codeBlock->isConstantRegisterIndex(srcVirtualRegister)) {
       
   140                 addArgument(m_jit->getConstantOperand(srcVirtualRegister));
       
   141                 return;
       
   142             }
       
   143 
       
   144             m_jit->emitLoad(srcVirtualRegister, JIT::regT1, JIT::regT0);
       
   145             addArgument(JIT::regT1, JIT::regT0);
       
   146         }
       
   147 
       
   148         void getArgument(size_t argumentNumber, JIT::RegisterID tag, JIT::RegisterID payload)
       
   149         {
       
   150             size_t stackIndex = JITSTACKFRAME_ARGS_INDEX + (argumentNumber * stackIndexStep);
       
   151             m_jit->peek(payload, stackIndex);
       
   152             m_jit->peek(tag, stackIndex + 1);
       
   153         }
       
   154 #else
       
   155         void addArgument(unsigned src, JIT::RegisterID scratchRegister) // src is a virtual register.
       
   156         {
       
   157             if (m_jit->m_codeBlock->isConstantRegisterIndex(src))
       
   158                 addArgument(JIT::ImmPtr(JSValue::encode(m_jit->m_codeBlock->getConstant(src))));
       
   159             else {
       
   160                 m_jit->loadPtr(JIT::Address(JIT::callFrameRegister, src * sizeof(Register)), scratchRegister);
       
   161                 addArgument(scratchRegister);
       
   162             }
       
   163             m_jit->killLastResultRegister();
       
   164         }
       
   165 #endif
       
   166 
       
   167         JIT::Call call()
       
   168         {
       
   169 #if ENABLE(OPCODE_SAMPLING)
       
   170             if (m_jit->m_bytecodeOffset != (unsigned)-1)
       
   171                 m_jit->sampleInstruction(m_jit->m_codeBlock->instructions().begin() + m_jit->m_bytecodeOffset, true);
       
   172 #endif
       
   173 
       
   174             m_jit->restoreArgumentReference();
       
   175             JIT::Call call = m_jit->call();
       
   176             m_jit->m_calls.append(CallRecord(call, m_jit->m_bytecodeOffset, m_stub.value()));
       
   177 
       
   178 #if ENABLE(OPCODE_SAMPLING)
       
   179             if (m_jit->m_bytecodeOffset != (unsigned)-1)
       
   180                 m_jit->sampleInstruction(m_jit->m_codeBlock->instructions().begin() + m_jit->m_bytecodeOffset, false);
       
   181 #endif
       
   182 
       
   183 #if USE(JSVALUE32_64)
       
   184             m_jit->unmap();
       
   185 #else
       
   186             m_jit->killLastResultRegister();
       
   187 #endif
       
   188             return call;
       
   189         }
       
   190 
       
   191 #if USE(JSVALUE32_64)
       
   192         JIT::Call call(unsigned dst) // dst is a virtual register.
       
   193         {
       
   194             ASSERT(m_returnType == Value || m_returnType == Cell);
       
   195             JIT::Call call = this->call();
       
   196             if (m_returnType == Value)
       
   197                 m_jit->emitStore(dst, JIT::regT1, JIT::regT0);
       
   198             else
       
   199                 m_jit->emitStoreCell(dst, JIT::returnValueRegister);
       
   200             return call;
       
   201         }
       
   202 #else
       
   203         JIT::Call call(unsigned dst) // dst is a virtual register.
       
   204         {
       
   205             ASSERT(m_returnType == VoidPtr || m_returnType == Cell);
       
   206             JIT::Call call = this->call();
       
   207             m_jit->emitPutVirtualRegister(dst);
       
   208             return call;
       
   209         }
       
   210 #endif
       
   211 
       
   212         JIT::Call call(JIT::RegisterID dst) // dst is a machine register.
       
   213         {
       
   214 #if USE(JSVALUE32_64)
       
   215             ASSERT(m_returnType == Value || m_returnType == VoidPtr || m_returnType == Int || m_returnType == Cell);
       
   216 #else
       
   217             ASSERT(m_returnType == VoidPtr || m_returnType == Int || m_returnType == Cell);
       
   218 #endif
       
   219             JIT::Call call = this->call();
       
   220             if (dst != JIT::returnValueRegister)
       
   221                 m_jit->move(JIT::returnValueRegister, dst);
       
   222             return call;
       
   223         }
       
   224 
       
   225     private:
       
   226         static const size_t stackIndexStep = sizeof(EncodedJSValue) == 2 * sizeof(void*) ? 2 : 1;
       
   227 
       
   228         JIT* m_jit;
       
   229         FunctionPtr m_stub;
       
   230         enum { Void, VoidPtr, Int, Value, Cell } m_returnType;
       
   231         size_t m_stackIndex;
       
   232     };
       
   233 }
       
   234 
       
   235 #endif // ENABLE(JIT)
       
   236 
       
   237 #endif // JITStubCall_h