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
))
41 , m_stackIndex(JITSTACKFRAME_ARGS_INDEX
)
45 JITStubCall(JIT
* jit
, JSPropertyNameIterator
* (JIT_STUB
*stub
)(STUB_ARGS_DECLARATION
))
49 , m_stackIndex(JITSTACKFRAME_ARGS_INDEX
)
53 JITStubCall(JIT
* jit
, void* (JIT_STUB
*stub
)(STUB_ARGS_DECLARATION
))
56 , m_returnType(VoidPtr
)
57 , m_stackIndex(JITSTACKFRAME_ARGS_INDEX
)
61 JITStubCall(JIT
* jit
, int (JIT_STUB
*stub
)(STUB_ARGS_DECLARATION
))
65 , m_stackIndex(JITSTACKFRAME_ARGS_INDEX
)
69 JITStubCall(JIT
* jit
, bool (JIT_STUB
*stub
)(STUB_ARGS_DECLARATION
))
73 , m_stackIndex(JITSTACKFRAME_ARGS_INDEX
)
77 JITStubCall(JIT
* jit
, void (JIT_STUB
*stub
)(STUB_ARGS_DECLARATION
))
81 , m_stackIndex(JITSTACKFRAME_ARGS_INDEX
)
86 JITStubCall(JIT
* jit
, EncodedJSValue (JIT_STUB
*stub
)(STUB_ARGS_DECLARATION
))
90 , m_stackIndex(JITSTACKFRAME_ARGS_INDEX
)
95 // Arguments are added first to last.
99 m_stackIndex
+= stackIndexStep
;
102 void addArgument(JIT::TrustedImm32 argument
)
104 m_jit
->poke(argument
, m_stackIndex
);
105 m_stackIndex
+= stackIndexStep
;
108 void addArgument(JIT::Imm32 argument
)
110 m_jit
->poke(argument
, m_stackIndex
);
111 m_stackIndex
+= stackIndexStep
;
114 void addArgument(JIT::TrustedImmPtr argument
)
116 m_jit
->poke(argument
, m_stackIndex
);
117 m_stackIndex
+= stackIndexStep
;
120 void addArgument(JIT::ImmPtr argument
)
122 m_jit
->poke(argument
, m_stackIndex
);
123 m_stackIndex
+= stackIndexStep
;
126 void addArgument(JIT::RegisterID argument
)
128 m_jit
->poke(argument
, m_stackIndex
);
129 m_stackIndex
+= stackIndexStep
;
132 #if USE(JSVALUE32_64)
133 void addArgument(const JSValue
& value
)
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
;
141 void addArgument(JIT::RegisterID tag
, JIT::RegisterID payload
)
143 m_jit
->poke(payload
, m_stackIndex
);
144 m_jit
->poke(tag
, m_stackIndex
+ 1);
145 m_stackIndex
+= stackIndexStep
;
148 #if USE(JSVALUE32_64)
149 void addArgument(unsigned srcVirtualRegister
)
151 if (m_jit
->m_codeBlock
->isConstantRegisterIndex(srcVirtualRegister
)) {
152 addArgument(m_jit
->getConstantOperand(srcVirtualRegister
));
156 m_jit
->emitLoad(srcVirtualRegister
, JIT::regT1
, JIT::regT0
);
157 addArgument(JIT::regT1
, JIT::regT0
);
160 void getArgument(size_t argumentNumber
, JIT::RegisterID tag
, JIT::RegisterID payload
)
162 size_t stackIndex
= JITSTACKFRAME_ARGS_INDEX
+ (argumentNumber
* stackIndexStep
);
163 m_jit
->peek(payload
, stackIndex
);
164 m_jit
->peek(tag
, stackIndex
+ 1);
167 void addArgument(unsigned src
, JIT::RegisterID scratchRegister
) // src is a virtual register.
169 if (m_jit
->m_codeBlock
->isConstantRegisterIndex(src
))
170 addArgument(JIT::ImmPtr(JSValue::encode(m_jit
->m_codeBlock
->getConstant(src
))));
172 m_jit
->loadPtr(JIT::Address(JIT::callFrameRegister
, src
* sizeof(Register
)), scratchRegister
);
173 addArgument(scratchRegister
);
175 m_jit
->killLastResultRegister();
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);
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()));
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);
196 #if USE(JSVALUE32_64)
199 m_jit
->killLastResultRegister();
204 #if USE(JSVALUE32_64)
205 JIT::Call
call(unsigned dst
) // dst is a virtual register.
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
);
212 m_jit
->emitStoreCell(dst
, JIT::returnValueRegister
);
216 JIT::Call
callWithValueProfiling(unsigned dst
)
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
);
227 m_jit
->emitStoreCell(dst
, JIT::returnValueRegister
);
231 JIT::Call
call(unsigned dst
) // dst is a virtual register.
233 ASSERT(m_returnType
== VoidPtr
|| m_returnType
== Cell
);
234 JIT::Call call
= this->call();
235 m_jit
->emitPutVirtualRegister(dst
);
239 JIT::Call
callWithValueProfiling(unsigned dst
)
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
);
250 JIT::Call
call(JIT::RegisterID dst
) // dst is a machine register.
252 #if USE(JSVALUE32_64)
253 ASSERT(m_returnType
== Value
|| m_returnType
== VoidPtr
|| m_returnType
== Int
|| m_returnType
== Cell
);
255 ASSERT(m_returnType
== VoidPtr
|| m_returnType
== Int
|| m_returnType
== Cell
);
257 JIT::Call call
= this->call();
258 if (dst
!= JIT::returnValueRegister
)
259 m_jit
->move(JIT::returnValueRegister
, dst
);
264 static const size_t stackIndexStep
= sizeof(EncodedJSValue
) == 2 * sizeof(void*) ? 2 : 1;
268 enum { Void
, VoidPtr
, Int
, Value
, Cell
} m_returnType
;
273 #endif // ENABLE(JIT)
275 #endif // JITStubCall_h