2 * Copyright (C) 2008 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
29 #include "MacroAssemblerCodeRef.h"
37 JITStubCall(JIT
* jit
, JSObject
* (JIT_STUB
*stub
)(STUB_ARGS_DECLARATION
))
40 #if USE(JSVALUE32_64) || !ASSERT_DISABLED
43 , m_stackIndex(JITSTACKFRAME_ARGS_INDEX
)
47 JITStubCall(JIT
* jit
, JSPropertyNameIterator
* (JIT_STUB
*stub
)(STUB_ARGS_DECLARATION
))
50 #if USE(JSVALUE32_64) || !ASSERT_DISABLED
53 , m_stackIndex(JITSTACKFRAME_ARGS_INDEX
)
57 JITStubCall(JIT
* jit
, void* (JIT_STUB
*stub
)(STUB_ARGS_DECLARATION
))
60 #if USE(JSVALUE32_64) || !ASSERT_DISABLED
61 , m_returnType(VoidPtr
)
63 , m_stackIndex(JITSTACKFRAME_ARGS_INDEX
)
67 JITStubCall(JIT
* jit
, int (JIT_STUB
*stub
)(STUB_ARGS_DECLARATION
))
70 #if USE(JSVALUE32_64) || !ASSERT_DISABLED
73 , m_stackIndex(JITSTACKFRAME_ARGS_INDEX
)
77 JITStubCall(JIT
* jit
, bool (JIT_STUB
*stub
)(STUB_ARGS_DECLARATION
))
80 #if USE(JSVALUE32_64) || !ASSERT_DISABLED
83 , m_stackIndex(JITSTACKFRAME_ARGS_INDEX
)
87 JITStubCall(JIT
* jit
, void (JIT_STUB
*stub
)(STUB_ARGS_DECLARATION
))
90 #if USE(JSVALUE32_64) || !ASSERT_DISABLED
93 , m_stackIndex(JITSTACKFRAME_ARGS_INDEX
)
97 JITStubCall(JIT
* jit
, EncodedJSValue (JIT_STUB
*stub
)(STUB_ARGS_DECLARATION
))
100 #if USE(JSVALUE32_64) || !ASSERT_DISABLED
101 , m_returnType(Value
)
103 , m_stackIndex(JITSTACKFRAME_ARGS_INDEX
)
107 // Arguments are added first to last.
111 m_stackIndex
+= stackIndexStep
;
114 void addArgument(JIT::TrustedImm32 argument
)
116 m_jit
->poke(argument
, m_stackIndex
);
117 m_stackIndex
+= stackIndexStep
;
120 void addArgument(JIT::Imm32 argument
)
122 m_jit
->poke(argument
, m_stackIndex
);
123 m_stackIndex
+= stackIndexStep
;
126 void addArgument(JIT::TrustedImmPtr argument
)
128 m_jit
->poke(argument
, m_stackIndex
);
129 m_stackIndex
+= stackIndexStep
;
132 void addArgument(JIT::ImmPtr argument
)
134 m_jit
->poke(argument
, m_stackIndex
);
135 m_stackIndex
+= stackIndexStep
;
138 void addArgument(JIT::RegisterID argument
)
140 #if USE(JSVALUE32_64)
141 m_jit
->poke(argument
, m_stackIndex
);
143 m_jit
->poke64(argument
, m_stackIndex
);
145 m_stackIndex
+= stackIndexStep
;
148 #if USE(JSVALUE32_64)
149 void addArgument(const JSValue
& value
)
151 m_jit
->poke(JIT::Imm32(value
.payload()), m_stackIndex
);
152 m_jit
->poke(JIT::Imm32(value
.tag()), m_stackIndex
+ 1);
153 m_stackIndex
+= stackIndexStep
;
156 void addArgument(JIT::TrustedImm64 argument
)
158 m_jit
->poke(argument
, m_stackIndex
);
159 m_stackIndex
+= stackIndexStep
;
162 void addArgument(JIT::Imm64 argument
)
164 m_jit
->poke(argument
, m_stackIndex
);
165 m_stackIndex
+= stackIndexStep
;
169 void addArgument(JIT::RegisterID tag
, JIT::RegisterID payload
)
171 m_jit
->poke(payload
, m_stackIndex
);
172 m_jit
->poke(tag
, m_stackIndex
+ 1);
173 m_stackIndex
+= stackIndexStep
;
176 #if USE(JSVALUE32_64)
177 void addArgument(unsigned srcVirtualRegister
)
179 if (m_jit
->m_codeBlock
->isConstantRegisterIndex(srcVirtualRegister
)) {
180 addArgument(m_jit
->getConstantOperand(srcVirtualRegister
));
184 m_jit
->emitLoad(srcVirtualRegister
, JIT::regT1
, JIT::regT0
);
185 addArgument(JIT::regT1
, JIT::regT0
);
188 void getArgument(size_t argumentNumber
, JIT::RegisterID tag
, JIT::RegisterID payload
)
190 size_t stackIndex
= JITSTACKFRAME_ARGS_INDEX
+ (argumentNumber
* stackIndexStep
);
191 m_jit
->peek(payload
, stackIndex
);
192 m_jit
->peek(tag
, stackIndex
+ 1);
195 void addArgument(unsigned src
, JIT::RegisterID scratchRegister
) // src is a virtual register.
197 if (m_jit
->m_codeBlock
->isConstantRegisterIndex(src
))
198 addArgument(JIT::Imm64(JSValue::encode(m_jit
->m_codeBlock
->getConstant(src
))));
200 m_jit
->load64(JIT::Address(JIT::callFrameRegister
, src
* sizeof(Register
)), scratchRegister
);
201 addArgument(scratchRegister
);
203 m_jit
->killLastResultRegister();
209 #if ENABLE(OPCODE_SAMPLING)
210 if (m_jit
->m_bytecodeOffset
!= (unsigned)-1)
211 m_jit
->sampleInstruction(m_jit
->m_codeBlock
->instructions().begin() + m_jit
->m_bytecodeOffset
, true);
214 m_jit
->restoreArgumentReference();
215 m_jit
->updateTopCallFrame();
216 JIT::Call call
= m_jit
->call();
217 m_jit
->m_calls
.append(CallRecord(call
, m_jit
->m_bytecodeOffset
, m_stub
.value()));
219 #if ENABLE(OPCODE_SAMPLING)
220 if (m_jit
->m_bytecodeOffset
!= (unsigned)-1)
221 m_jit
->sampleInstruction(m_jit
->m_codeBlock
->instructions().begin() + m_jit
->m_bytecodeOffset
, false);
224 #if USE(JSVALUE32_64)
227 m_jit
->killLastResultRegister();
232 #if USE(JSVALUE32_64)
233 JIT::Call
call(unsigned dst
) // dst is a virtual register.
235 ASSERT(m_returnType
== Value
|| m_returnType
== Cell
);
236 JIT::Call call
= this->call();
237 if (m_returnType
== Value
)
238 m_jit
->emitStore(dst
, JIT::regT1
, JIT::regT0
);
240 m_jit
->emitStoreCell(dst
, JIT::returnValueRegister
);
244 JIT::Call
callWithValueProfiling(unsigned dst
)
246 ASSERT(m_returnType
== Value
|| m_returnType
== Cell
);
247 JIT::Call call
= this->call();
248 ASSERT(JIT::returnValueRegister
== JIT::regT0
);
249 if (m_returnType
== Cell
)
250 m_jit
->move(JIT::TrustedImm32(JSValue::CellTag
), JIT::regT1
);
251 m_jit
->emitValueProfilingSite();
252 if (m_returnType
== Value
)
253 m_jit
->emitStore(dst
, JIT::regT1
, JIT::regT0
);
255 m_jit
->emitStoreCell(dst
, JIT::returnValueRegister
);
259 JIT::Call
call(unsigned dst
) // dst is a virtual register.
261 ASSERT(m_returnType
== Value
|| m_returnType
== Cell
);
262 JIT::Call call
= this->call();
263 m_jit
->emitPutVirtualRegister(dst
);
267 JIT::Call
callWithValueProfiling(unsigned dst
)
269 ASSERT(m_returnType
== Value
|| m_returnType
== Cell
);
270 JIT::Call call
= this->call();
271 ASSERT(JIT::returnValueRegister
== JIT::regT0
);
272 m_jit
->emitValueProfilingSite();
273 m_jit
->emitPutVirtualRegister(dst
);
278 JIT::Call
call(JIT::RegisterID dst
) // dst is a machine register.
280 #if USE(JSVALUE32_64) || !ASSERT_DISABLED
281 ASSERT(m_returnType
== Value
|| m_returnType
== VoidPtr
|| m_returnType
== Int
|| m_returnType
== Cell
);
283 JIT::Call call
= this->call();
284 if (dst
!= JIT::returnValueRegister
)
285 m_jit
->move(JIT::returnValueRegister
, dst
);
290 static const size_t stackIndexStep
= sizeof(EncodedJSValue
) == 2 * sizeof(void*) ? 2 : 1;
294 #if USE(JSVALUE32_64) || !ASSERT_DISABLED
295 enum { Void
, VoidPtr
, Int
, Value
, Cell
} m_returnType
;
301 #endif // ENABLE(JIT)
303 #endif // JITStubCall_h