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: JITStubCall(JIT * jit,JSObject * (JIT_STUB * stub)(STUB_ARGS_DECLARATION))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 JITStubCall(JIT * jit,JSPropertyNameIterator * (JIT_STUB * stub)(STUB_ARGS_DECLARATION))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 JITStubCall(JIT * jit,void * (JIT_STUB * stub)(STUB_ARGS_DECLARATION))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 JITStubCall(JIT * jit,int (JIT_STUB * stub)(STUB_ARGS_DECLARATION))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 JITStubCall(JIT * jit,bool (JIT_STUB * stub)(STUB_ARGS_DECLARATION))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 JITStubCall(JIT * jit,void (JIT_STUB * stub)(STUB_ARGS_DECLARATION))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) JITStubCall(JIT * jit,EncodedJSValue (JIT_STUB * stub)(STUB_ARGS_DECLARATION))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 skipArgument()97 void skipArgument() 98 { 99 m_stackIndex += stackIndexStep; 100 } 101 addArgument(JIT::TrustedImm32 argument)102 void addArgument(JIT::TrustedImm32 argument) 103 { 104 m_jit->poke(argument, m_stackIndex); 105 m_stackIndex += stackIndexStep; 106 } 107 addArgument(JIT::TrustedImmPtr argument)108 void addArgument(JIT::TrustedImmPtr argument) 109 { 110 m_jit->poke(argument, m_stackIndex); 111 m_stackIndex += stackIndexStep; 112 } 113 addArgument(JIT::RegisterID argument)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) addArgument(const JSValue & value)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 addArgument(JIT::RegisterID tag,JIT::RegisterID payload)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) addArgument(unsigned srcVirtualRegister)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 getArgument(size_t argumentNumber,JIT::RegisterID tag,JIT::RegisterID payload)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 addArgument(unsigned src,JIT::RegisterID scratchRegister)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 call()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) call(unsigned dst)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 call(unsigned dst)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 call(JIT::RegisterID dst)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