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::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         void addArgument(const JSValue& value)
    121         {
    122             m_jit->poke(JIT::Imm32(value.payload()), m_stackIndex);
    123             m_jit->poke(JIT::Imm32(value.tag()), m_stackIndex + 1);
    124             m_stackIndex += stackIndexStep;
    125         }
    126 
    127         void addArgument(JIT::RegisterID tag, JIT::RegisterID payload)
    128         {
    129             m_jit->poke(payload, m_stackIndex);
    130             m_jit->poke(tag, m_stackIndex + 1);
    131             m_stackIndex += stackIndexStep;
    132         }
    133 
    134 #if USE(JSVALUE32_64)
    135         void addArgument(unsigned srcVirtualRegister)
    136         {
    137             if (m_jit->m_codeBlock->isConstantRegisterIndex(srcVirtualRegister)) {
    138                 addArgument(m_jit->getConstantOperand(srcVirtualRegister));
    139                 return;
    140             }
    141 
    142             m_jit->emitLoad(srcVirtualRegister, JIT::regT1, JIT::regT0);
    143             addArgument(JIT::regT1, JIT::regT0);
    144         }
    145 
    146         void getArgument(size_t argumentNumber, JIT::RegisterID tag, JIT::RegisterID payload)
    147         {
    148             size_t stackIndex = JITSTACKFRAME_ARGS_INDEX + (argumentNumber * stackIndexStep);
    149             m_jit->peek(payload, stackIndex);
    150             m_jit->peek(tag, stackIndex + 1);
    151         }
    152 #else
    153         void addArgument(unsigned src, JIT::RegisterID scratchRegister) // src is a virtual register.
    154         {
    155             if (m_jit->m_codeBlock->isConstantRegisterIndex(src))
    156                 addArgument(JIT::ImmPtr(JSValue::encode(m_jit->m_codeBlock->getConstant(src))));
    157             else {
    158                 m_jit->loadPtr(JIT::Address(JIT::callFrameRegister, src * sizeof(Register)), scratchRegister);
    159                 addArgument(scratchRegister);
    160             }
    161             m_jit->killLastResultRegister();
    162         }
    163 #endif
    164 
    165         JIT::Call call()
    166         {
    167 #if ENABLE(OPCODE_SAMPLING)
    168             if (m_jit->m_bytecodeIndex != (unsigned)-1)
    169                 m_jit->sampleInstruction(m_jit->m_codeBlock->instructions().begin() + m_jit->m_bytecodeIndex, true);
    170 #endif
    171 
    172             m_jit->restoreArgumentReference();
    173             JIT::Call call = m_jit->call();
    174             m_jit->m_calls.append(CallRecord(call, m_jit->m_bytecodeIndex, m_stub.value()));
    175 
    176 #if ENABLE(OPCODE_SAMPLING)
    177             if (m_jit->m_bytecodeIndex != (unsigned)-1)
    178                 m_jit->sampleInstruction(m_jit->m_codeBlock->instructions().begin() + m_jit->m_bytecodeIndex, false);
    179 #endif
    180 
    181 #if USE(JSVALUE32_64)
    182             m_jit->unmap();
    183 #else
    184             m_jit->killLastResultRegister();
    185 #endif
    186             return call;
    187         }
    188 
    189 #if USE(JSVALUE32_64)
    190         JIT::Call call(unsigned dst) // dst is a virtual register.
    191         {
    192             ASSERT(m_returnType == Value || m_returnType == Cell);
    193             JIT::Call call = this->call();
    194             if (m_returnType == Value)
    195                 m_jit->emitStore(dst, JIT::regT1, JIT::regT0);
    196             else
    197                 m_jit->emitStoreCell(dst, JIT::returnValueRegister);
    198             return call;
    199         }
    200 #else
    201         JIT::Call call(unsigned dst) // dst is a virtual register.
    202         {
    203             ASSERT(m_returnType == VoidPtr || m_returnType == Cell);
    204             JIT::Call call = this->call();
    205             m_jit->emitPutVirtualRegister(dst);
    206             return call;
    207         }
    208 #endif
    209 
    210         JIT::Call call(JIT::RegisterID dst) // dst is a machine register.
    211         {
    212 #if USE(JSVALUE32_64)
    213             ASSERT(m_returnType == Value || m_returnType == VoidPtr || m_returnType == Int || m_returnType == Cell);
    214 #else
    215             ASSERT(m_returnType == VoidPtr || m_returnType == Int || m_returnType == Cell);
    216 #endif
    217             JIT::Call call = this->call();
    218             if (dst != JIT::returnValueRegister)
    219                 m_jit->move(JIT::returnValueRegister, dst);
    220             return call;
    221         }
    222 
    223     private:
    224         static const size_t stackIndexStep = sizeof(EncodedJSValue) == 2 * sizeof(void*) ? 2 : 1;
    225 
    226         JIT* m_jit;
    227         FunctionPtr m_stub;
    228         enum { Void, VoidPtr, Int, Value, Cell } m_returnType;
    229         size_t m_stackIndex;
    230     };
    231 }
    232 
    233 #endif // ENABLE(JIT)
    234 
    235 #endif // JITStubCall_h
    236