]>
Commit | Line | Data |
---|---|---|
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 <wtf/Platform.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(reinterpret_cast<void*>(stub)) | |
40 | , m_returnType(Cell) | |
41 | , m_stackIndex(stackIndexStart) | |
42 | { | |
43 | } | |
44 | ||
45 | JITStubCall(JIT* jit, JSPropertyNameIterator* (JIT_STUB *stub)(STUB_ARGS_DECLARATION)) | |
46 | : m_jit(jit) | |
47 | , m_stub(reinterpret_cast<void*>(stub)) | |
48 | , m_returnType(Cell) | |
49 | , m_stackIndex(stackIndexStart) | |
50 | { | |
51 | } | |
52 | ||
53 | JITStubCall(JIT* jit, void* (JIT_STUB *stub)(STUB_ARGS_DECLARATION)) | |
54 | : m_jit(jit) | |
55 | , m_stub(reinterpret_cast<void*>(stub)) | |
56 | , m_returnType(VoidPtr) | |
57 | , m_stackIndex(stackIndexStart) | |
58 | { | |
59 | } | |
60 | ||
61 | JITStubCall(JIT* jit, int (JIT_STUB *stub)(STUB_ARGS_DECLARATION)) | |
62 | : m_jit(jit) | |
63 | , m_stub(reinterpret_cast<void*>(stub)) | |
64 | , m_returnType(Int) | |
65 | , m_stackIndex(stackIndexStart) | |
66 | { | |
67 | } | |
68 | ||
69 | JITStubCall(JIT* jit, bool (JIT_STUB *stub)(STUB_ARGS_DECLARATION)) | |
70 | : m_jit(jit) | |
71 | , m_stub(reinterpret_cast<void*>(stub)) | |
72 | , m_returnType(Int) | |
73 | , m_stackIndex(stackIndexStart) | |
74 | { | |
75 | } | |
76 | ||
77 | JITStubCall(JIT* jit, void (JIT_STUB *stub)(STUB_ARGS_DECLARATION)) | |
78 | : m_jit(jit) | |
79 | , m_stub(reinterpret_cast<void*>(stub)) | |
80 | , m_returnType(Void) | |
81 | , m_stackIndex(stackIndexStart) | |
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(reinterpret_cast<void*>(stub)) | |
89 | , m_returnType(Value) | |
90 | , m_stackIndex(stackIndexStart) | |
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 = stackIndexStart + (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)); | |
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 | static const size_t stackIndexStart = 1; // Index 0 is reserved for restoreArgumentReference(). | |
226 | ||
227 | JIT* m_jit; | |
228 | void* m_stub; | |
229 | enum { Void, VoidPtr, Int, Value, Cell } m_returnType; | |
230 | size_t m_stackIndex; | |
231 | }; | |
232 | } | |
233 | ||
234 | #endif // ENABLE(JIT) | |
235 | ||
236 | #endif // JITStubCall_h |