Home | History | Annotate | Download | only in jit
      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::TrustedImm32 argument)
    103         {
    104             m_jit->poke(argument, m_stackIndex);
    105             m_stackIndex += stackIndexStep;
    106         }
    107 
    108         void addArgument(JIT::TrustedImmPtr 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
    238