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
33namespace 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(value: argument, index: m_stackIndex);
105 m_stackIndex += stackIndexStep;
106 }
107
108 void addArgument(JIT::ImmPtr argument)
109 {
110 m_jit->poke(imm: argument, index: m_stackIndex);
111 m_stackIndex += stackIndexStep;
112 }
113
114 void addArgument(JIT::RegisterID argument)
115 {
116 m_jit->poke(src: argument, index: m_stackIndex);
117 m_stackIndex += stackIndexStep;
118 }
119
120 void addArgument(const JSValue& value)
121 {
122 m_jit->poke(value: JIT::Imm32(value.payload()), index: m_stackIndex);
123 m_jit->poke(value: JIT::Imm32(value.tag()), index: m_stackIndex + 1);
124 m_stackIndex += stackIndexStep;
125 }
126
127 void addArgument(JIT::RegisterID tag, JIT::RegisterID payload)
128 {
129 m_jit->poke(src: payload, index: m_stackIndex);
130 m_jit->poke(src: tag, index: 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(index: src))
156 addArgument(argument: JIT::ImmPtr(JSValue::encode(value: m_jit->m_codeBlock->getConstant(index: src))));
157 else {
158 m_jit->loadPtr(address: JIT::Address(JIT::callFrameRegister, src * sizeof(Register)), dest: scratchRegister);
159 addArgument(argument: 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(val: 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(src: JIT::returnValueRegister, dest: 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

source code of qtscript/src/3rdparty/javascriptcore/JavaScriptCore/jit/JITStubCall.h