]> git.saurik.com Git - apple/javascriptcore.git/blob - jit/JITStubCall.h
JavaScriptCore-1097.13.tar.gz
[apple/javascriptcore.git] / jit / JITStubCall.h
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::Imm32 argument)
109 {
110 m_jit->poke(argument, m_stackIndex);
111 m_stackIndex += stackIndexStep;
112 }
113
114 void addArgument(JIT::TrustedImmPtr argument)
115 {
116 m_jit->poke(argument, m_stackIndex);
117 m_stackIndex += stackIndexStep;
118 }
119
120 void addArgument(JIT::ImmPtr argument)
121 {
122 m_jit->poke(argument, m_stackIndex);
123 m_stackIndex += stackIndexStep;
124 }
125
126 void addArgument(JIT::RegisterID argument)
127 {
128 m_jit->poke(argument, m_stackIndex);
129 m_stackIndex += stackIndexStep;
130 }
131
132 #if USE(JSVALUE32_64)
133 void addArgument(const JSValue& value)
134 {
135 m_jit->poke(JIT::Imm32(value.payload()), m_stackIndex);
136 m_jit->poke(JIT::Imm32(value.tag()), m_stackIndex + 1);
137 m_stackIndex += stackIndexStep;
138 }
139 #endif
140
141 void addArgument(JIT::RegisterID tag, JIT::RegisterID payload)
142 {
143 m_jit->poke(payload, m_stackIndex);
144 m_jit->poke(tag, m_stackIndex + 1);
145 m_stackIndex += stackIndexStep;
146 }
147
148 #if USE(JSVALUE32_64)
149 void addArgument(unsigned srcVirtualRegister)
150 {
151 if (m_jit->m_codeBlock->isConstantRegisterIndex(srcVirtualRegister)) {
152 addArgument(m_jit->getConstantOperand(srcVirtualRegister));
153 return;
154 }
155
156 m_jit->emitLoad(srcVirtualRegister, JIT::regT1, JIT::regT0);
157 addArgument(JIT::regT1, JIT::regT0);
158 }
159
160 void getArgument(size_t argumentNumber, JIT::RegisterID tag, JIT::RegisterID payload)
161 {
162 size_t stackIndex = JITSTACKFRAME_ARGS_INDEX + (argumentNumber * stackIndexStep);
163 m_jit->peek(payload, stackIndex);
164 m_jit->peek(tag, stackIndex + 1);
165 }
166 #else
167 void addArgument(unsigned src, JIT::RegisterID scratchRegister) // src is a virtual register.
168 {
169 if (m_jit->m_codeBlock->isConstantRegisterIndex(src))
170 addArgument(JIT::ImmPtr(JSValue::encode(m_jit->m_codeBlock->getConstant(src))));
171 else {
172 m_jit->loadPtr(JIT::Address(JIT::callFrameRegister, src * sizeof(Register)), scratchRegister);
173 addArgument(scratchRegister);
174 }
175 m_jit->killLastResultRegister();
176 }
177 #endif
178
179 JIT::Call call()
180 {
181 #if ENABLE(OPCODE_SAMPLING)
182 if (m_jit->m_bytecodeOffset != (unsigned)-1)
183 m_jit->sampleInstruction(m_jit->m_codeBlock->instructions().begin() + m_jit->m_bytecodeOffset, true);
184 #endif
185
186 m_jit->restoreArgumentReference();
187 m_jit->updateTopCallFrame();
188 JIT::Call call = m_jit->call();
189 m_jit->m_calls.append(CallRecord(call, m_jit->m_bytecodeOffset, m_stub.value()));
190
191 #if ENABLE(OPCODE_SAMPLING)
192 if (m_jit->m_bytecodeOffset != (unsigned)-1)
193 m_jit->sampleInstruction(m_jit->m_codeBlock->instructions().begin() + m_jit->m_bytecodeOffset, false);
194 #endif
195
196 #if USE(JSVALUE32_64)
197 m_jit->unmap();
198 #else
199 m_jit->killLastResultRegister();
200 #endif
201 return call;
202 }
203
204 #if USE(JSVALUE32_64)
205 JIT::Call call(unsigned dst) // dst is a virtual register.
206 {
207 ASSERT(m_returnType == Value || m_returnType == Cell);
208 JIT::Call call = this->call();
209 if (m_returnType == Value)
210 m_jit->emitStore(dst, JIT::regT1, JIT::regT0);
211 else
212 m_jit->emitStoreCell(dst, JIT::returnValueRegister);
213 return call;
214 }
215
216 JIT::Call callWithValueProfiling(unsigned dst)
217 {
218 ASSERT(m_returnType == Value || m_returnType == Cell);
219 JIT::Call call = this->call();
220 ASSERT(JIT::returnValueRegister == JIT::regT0);
221 if (m_returnType == Cell)
222 m_jit->move(JIT::TrustedImm32(JSValue::CellTag), JIT::regT1);
223 m_jit->emitValueProfilingSite();
224 if (m_returnType == Value)
225 m_jit->emitStore(dst, JIT::regT1, JIT::regT0);
226 else
227 m_jit->emitStoreCell(dst, JIT::returnValueRegister);
228 return call;
229 }
230 #else
231 JIT::Call call(unsigned dst) // dst is a virtual register.
232 {
233 ASSERT(m_returnType == VoidPtr || m_returnType == Cell);
234 JIT::Call call = this->call();
235 m_jit->emitPutVirtualRegister(dst);
236 return call;
237 }
238
239 JIT::Call callWithValueProfiling(unsigned dst)
240 {
241 ASSERT(m_returnType == VoidPtr || m_returnType == Cell);
242 JIT::Call call = this->call();
243 ASSERT(JIT::returnValueRegister == JIT::regT0);
244 m_jit->emitValueProfilingSite();
245 m_jit->emitPutVirtualRegister(dst);
246 return call;
247 }
248 #endif
249
250 JIT::Call call(JIT::RegisterID dst) // dst is a machine register.
251 {
252 #if USE(JSVALUE32_64)
253 ASSERT(m_returnType == Value || m_returnType == VoidPtr || m_returnType == Int || m_returnType == Cell);
254 #else
255 ASSERT(m_returnType == VoidPtr || m_returnType == Int || m_returnType == Cell);
256 #endif
257 JIT::Call call = this->call();
258 if (dst != JIT::returnValueRegister)
259 m_jit->move(JIT::returnValueRegister, dst);
260 return call;
261 }
262
263 private:
264 static const size_t stackIndexStep = sizeof(EncodedJSValue) == 2 * sizeof(void*) ? 2 : 1;
265
266 JIT* m_jit;
267 FunctionPtr m_stub;
268 enum { Void, VoidPtr, Int, Value, Cell } m_returnType;
269 size_t m_stackIndex;
270 };
271 }
272
273 #endif // ENABLE(JIT)
274
275 #endif // JITStubCall_h