]> git.saurik.com Git - apple/javascriptcore.git/blame - jit/JSInterfaceJIT.h
JavaScriptCore-1218.0.1.tar.gz
[apple/javascriptcore.git] / jit / JSInterfaceJIT.h
CommitLineData
4e4e5a6f
A
1/*
2 * Copyright (C) 2010 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. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#ifndef JSInterfaceJIT_h
27#define JSInterfaceJIT_h
28
6fe7ccc8 29#include "BytecodeConventions.h"
4e4e5a6f
A
30#include "JITCode.h"
31#include "JITStubs.h"
93a37866
A
32#include "JSCJSValue.h"
33#include "JSStack.h"
6fe7ccc8 34#include "JSString.h"
4e4e5a6f 35#include "MacroAssembler.h"
4e4e5a6f
A
36#include <wtf/Vector.h>
37
93a37866
A
38#if ENABLE(JIT)
39
4e4e5a6f
A
40namespace JSC {
41 class JSInterfaceJIT : public MacroAssembler {
42 public:
43 // NOTES:
44 //
45 // regT0 has two special meanings. The return value from a stub
46 // call will always be in regT0, and by default (unless
47 // a register is specified) emitPutVirtualRegister() will store
48 // the value from regT0.
49 //
50 // regT3 is required to be callee-preserved.
51 //
52 // tempRegister2 is has no such dependencies. It is important that
53 // on x86/x86-64 it is ecx for performance reasons, since the
54 // MacroAssembler will need to plant register swaps if it is not -
55 // however the code will still function correctly.
56#if CPU(X86_64)
57 static const RegisterID returnValueRegister = X86Registers::eax;
58 static const RegisterID cachedResultRegister = X86Registers::eax;
93a37866 59#if !OS(WINDOWS)
4e4e5a6f 60 static const RegisterID firstArgumentRegister = X86Registers::edi;
93a37866
A
61#else
62 static const RegisterID firstArgumentRegister = X86Registers::ecx;
63#endif
64
6fe7ccc8
A
65#if ENABLE(VALUE_PROFILER)
66 static const RegisterID bucketCounterRegister = X86Registers::r10;
67#endif
93a37866 68
4e4e5a6f
A
69 static const RegisterID callFrameRegister = X86Registers::r13;
70 static const RegisterID tagTypeNumberRegister = X86Registers::r14;
71 static const RegisterID tagMaskRegister = X86Registers::r15;
93a37866 72
4e4e5a6f
A
73 static const RegisterID regT0 = X86Registers::eax;
74 static const RegisterID regT1 = X86Registers::edx;
75 static const RegisterID regT2 = X86Registers::ecx;
76 static const RegisterID regT3 = X86Registers::ebx;
93a37866 77
4e4e5a6f
A
78 static const FPRegisterID fpRegT0 = X86Registers::xmm0;
79 static const FPRegisterID fpRegT1 = X86Registers::xmm1;
80 static const FPRegisterID fpRegT2 = X86Registers::xmm2;
81 static const FPRegisterID fpRegT3 = X86Registers::xmm3;
93a37866
A
82
83 static const RegisterID nonArgGPR1 = X86Registers::eax; // regT0
4e4e5a6f
A
84#elif CPU(X86)
85 static const RegisterID returnValueRegister = X86Registers::eax;
86 static const RegisterID cachedResultRegister = X86Registers::eax;
87 // On x86 we always use fastcall conventions = but on
88 // OS X if might make more sense to just use regparm.
89 static const RegisterID firstArgumentRegister = X86Registers::ecx;
90
6fe7ccc8 91 static const RegisterID bucketCounterRegister = X86Registers::esi;
4e4e5a6f
A
92 static const RegisterID callFrameRegister = X86Registers::edi;
93
94 static const RegisterID regT0 = X86Registers::eax;
95 static const RegisterID regT1 = X86Registers::edx;
96 static const RegisterID regT2 = X86Registers::ecx;
97 static const RegisterID regT3 = X86Registers::ebx;
98
99 static const FPRegisterID fpRegT0 = X86Registers::xmm0;
100 static const FPRegisterID fpRegT1 = X86Registers::xmm1;
101 static const FPRegisterID fpRegT2 = X86Registers::xmm2;
102 static const FPRegisterID fpRegT3 = X86Registers::xmm3;
93a37866 103#elif CPU(ARM)
4e4e5a6f
A
104 static const RegisterID returnValueRegister = ARMRegisters::r0;
105 static const RegisterID cachedResultRegister = ARMRegisters::r0;
106 static const RegisterID firstArgumentRegister = ARMRegisters::r0;
6fe7ccc8
A
107
108#if ENABLE(VALUE_PROFILER)
109 static const RegisterID bucketCounterRegister = ARMRegisters::r7;
110#endif
111
4e4e5a6f
A
112 static const RegisterID regT0 = ARMRegisters::r0;
113 static const RegisterID regT1 = ARMRegisters::r1;
114 static const RegisterID regT2 = ARMRegisters::r2;
115 static const RegisterID regT3 = ARMRegisters::r4;
93a37866
A
116
117 // Update ctiTrampoline in JITStubs.cpp if these values are changed!
4e4e5a6f 118 static const RegisterID callFrameRegister = ARMRegisters::r5;
93a37866 119
4e4e5a6f
A
120 static const FPRegisterID fpRegT0 = ARMRegisters::d0;
121 static const FPRegisterID fpRegT1 = ARMRegisters::d1;
122 static const FPRegisterID fpRegT2 = ARMRegisters::d2;
123 static const FPRegisterID fpRegT3 = ARMRegisters::d3;
93a37866
A
124#elif CPU(ARM64)
125 static const RegisterID returnValueRegister = ARM64Registers::x0;
126 static const RegisterID cachedResultRegister = ARM64Registers::x0;
127 static const RegisterID firstArgumentRegister = ARM64Registers::x0;
128
129#if ENABLE(VALUE_PROFILER)
130 static const RegisterID bucketCounterRegister = ARM64Registers::x7;
131#endif
132
133 static const RegisterID regT0 = ARM64Registers::x0;
134 static const RegisterID regT1 = ARM64Registers::x1;
135 static const RegisterID regT2 = ARM64Registers::x2;
136 static const RegisterID regT3 = ARM64Registers::x23;
4e4e5a6f 137
93a37866
A
138 static const RegisterID callFrameRegister = ARM64Registers::x25;
139 static const RegisterID timeoutCheckRegister = ARM64Registers::x26;
140 static const RegisterID tagTypeNumberRegister = ARM64Registers::x27;
141 static const RegisterID tagMaskRegister = ARM64Registers::x28;
4e4e5a6f 142
93a37866
A
143 static const FPRegisterID fpRegT0 = ARM64Registers::q0;
144 static const FPRegisterID fpRegT1 = ARM64Registers::q1;
145 static const FPRegisterID fpRegT2 = ARM64Registers::q2;
146 static const FPRegisterID fpRegT3 = ARM64Registers::q3;
147
148 static const RegisterID nonArgGPR1 = ARM64Registers::x9;
4e4e5a6f
A
149#elif CPU(MIPS)
150 static const RegisterID returnValueRegister = MIPSRegisters::v0;
151 static const RegisterID cachedResultRegister = MIPSRegisters::v0;
152 static const RegisterID firstArgumentRegister = MIPSRegisters::a0;
153
93a37866
A
154#if ENABLE(VALUE_PROFILER)
155 static const RegisterID bucketCounterRegister = MIPSRegisters::s3;
156#endif
157
4e4e5a6f
A
158 // regT0 must be v0 for returning a 32-bit value.
159 static const RegisterID regT0 = MIPSRegisters::v0;
160
161 // regT1 must be v1 for returning a pair of 32-bit value.
162 static const RegisterID regT1 = MIPSRegisters::v1;
163
164 static const RegisterID regT2 = MIPSRegisters::t4;
165
166 // regT3 must be saved in the callee, so use an S register.
167 static const RegisterID regT3 = MIPSRegisters::s2;
168
169 static const RegisterID callFrameRegister = MIPSRegisters::s0;
4e4e5a6f
A
170
171 static const FPRegisterID fpRegT0 = MIPSRegisters::f4;
172 static const FPRegisterID fpRegT1 = MIPSRegisters::f6;
173 static const FPRegisterID fpRegT2 = MIPSRegisters::f8;
14957cd0
A
174 static const FPRegisterID fpRegT3 = MIPSRegisters::f10;
175#elif CPU(SH4)
14957cd0
A
176 static const RegisterID callFrameRegister = SH4Registers::fp;
177
178 static const RegisterID regT0 = SH4Registers::r0;
179 static const RegisterID regT1 = SH4Registers::r1;
180 static const RegisterID regT2 = SH4Registers::r2;
181 static const RegisterID regT3 = SH4Registers::r10;
182 static const RegisterID regT4 = SH4Registers::r4;
183 static const RegisterID regT5 = SH4Registers::r5;
184 static const RegisterID regT6 = SH4Registers::r6;
185 static const RegisterID regT7 = SH4Registers::r7;
186 static const RegisterID firstArgumentRegister =regT4;
187
188 static const RegisterID returnValueRegister = SH4Registers::r0;
189 static const RegisterID cachedResultRegister = SH4Registers::r0;
190
191 static const FPRegisterID fpRegT0 = SH4Registers::fr0;
192 static const FPRegisterID fpRegT1 = SH4Registers::fr2;
193 static const FPRegisterID fpRegT2 = SH4Registers::fr4;
194 static const FPRegisterID fpRegT3 = SH4Registers::fr6;
195 static const FPRegisterID fpRegT4 = SH4Registers::fr8;
196 static const FPRegisterID fpRegT5 = SH4Registers::fr10;
197 static const FPRegisterID fpRegT6 = SH4Registers::fr12;
198 static const FPRegisterID fpRegT7 = SH4Registers::fr14;
4e4e5a6f
A
199#else
200#error "JIT not supported on this platform."
201#endif
202
14957cd0
A
203#if USE(JSVALUE32_64)
204 // Can't just propogate JSValue::Int32Tag as visual studio doesn't like it
205 static const unsigned Int32Tag = 0xffffffff;
206 COMPILE_ASSERT(Int32Tag == JSValue::Int32Tag, Int32Tag_out_of_sync);
207#else
208 static const unsigned Int32Tag = TagTypeNumber >> 32;
209#endif
4e4e5a6f
A
210 inline Jump emitLoadJSCell(unsigned virtualRegisterIndex, RegisterID payload);
211 inline Jump emitLoadInt32(unsigned virtualRegisterIndex, RegisterID dst);
212 inline Jump emitLoadDouble(unsigned virtualRegisterIndex, FPRegisterID dst, RegisterID scratch);
213
214#if USE(JSVALUE32_64)
215 inline Jump emitJumpIfNotJSCell(unsigned virtualRegisterIndex);
14957cd0 216 inline Address tagFor(int index, RegisterID base = callFrameRegister);
4e4e5a6f
A
217#endif
218
14957cd0 219#if USE(JSVALUE64)
93a37866 220 Jump emitJumpIfNotJSCell(RegisterID);
4e4e5a6f
A
221 Jump emitJumpIfImmediateNumber(RegisterID reg);
222 Jump emitJumpIfNotImmediateNumber(RegisterID reg);
223 void emitFastArithImmToInt(RegisterID reg);
93a37866 224 void emitFastArithIntToImmNoCheck(RegisterID src, RegisterID dest);
4e4e5a6f
A
225#endif
226
93a37866
A
227 Jump emitJumpIfNotType(RegisterID baseReg, RegisterID scratchReg, JSType);
228
229 void emitGetFromCallFrameHeaderPtr(JSStack::CallFrameHeaderEntry, RegisterID to, RegisterID from = callFrameRegister);
230 void emitPutToCallFrameHeader(RegisterID from, JSStack::CallFrameHeaderEntry);
231 void emitPutImmediateToCallFrameHeader(void* value, JSStack::CallFrameHeaderEntry);
232 void emitPutCellToCallFrameHeader(RegisterID from, JSStack::CallFrameHeaderEntry);
233
234 void preserveReturnAddressAfterCall(RegisterID);
235 void restoreReturnAddressBeforeReturn(RegisterID);
236 void restoreReturnAddressBeforeReturn(Address);
237 void restoreArgumentReference();
238
14957cd0
A
239 inline Address payloadFor(int index, RegisterID base = callFrameRegister);
240 inline Address intPayloadFor(int index, RegisterID base = callFrameRegister);
241 inline Address intTagFor(int index, RegisterID base = callFrameRegister);
242 inline Address addressFor(int index, RegisterID base = callFrameRegister);
4e4e5a6f
A
243 };
244
245 struct ThunkHelpers {
4e4e5a6f
A
246 static unsigned jsStringLengthOffset() { return OBJECT_OFFSETOF(JSString, m_length); }
247 static unsigned jsStringValueOffset() { return OBJECT_OFFSETOF(JSString, m_value); }
248 };
249
250#if USE(JSVALUE32_64)
251 inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadJSCell(unsigned virtualRegisterIndex, RegisterID payload)
252 {
253 loadPtr(payloadFor(virtualRegisterIndex), payload);
254 return emitJumpIfNotJSCell(virtualRegisterIndex);
255 }
256
257 inline JSInterfaceJIT::Jump JSInterfaceJIT::emitJumpIfNotJSCell(unsigned virtualRegisterIndex)
258 {
259 ASSERT(static_cast<int>(virtualRegisterIndex) < FirstConstantRegisterIndex);
14957cd0 260 return branch32(NotEqual, tagFor(virtualRegisterIndex), TrustedImm32(JSValue::CellTag));
4e4e5a6f
A
261 }
262
263 inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadInt32(unsigned virtualRegisterIndex, RegisterID dst)
264 {
265 ASSERT(static_cast<int>(virtualRegisterIndex) < FirstConstantRegisterIndex);
266 loadPtr(payloadFor(virtualRegisterIndex), dst);
14957cd0 267 return branch32(NotEqual, tagFor(static_cast<int>(virtualRegisterIndex)), TrustedImm32(JSValue::Int32Tag));
4e4e5a6f
A
268 }
269
14957cd0 270 inline JSInterfaceJIT::Address JSInterfaceJIT::tagFor(int virtualRegisterIndex, RegisterID base)
4e4e5a6f 271 {
14957cd0
A
272 ASSERT(virtualRegisterIndex < FirstConstantRegisterIndex);
273 return Address(base, (static_cast<unsigned>(virtualRegisterIndex) * sizeof(Register)) + OBJECT_OFFSETOF(JSValue, u.asBits.tag));
4e4e5a6f
A
274 }
275
14957cd0 276 inline JSInterfaceJIT::Address JSInterfaceJIT::payloadFor(int virtualRegisterIndex, RegisterID base)
4e4e5a6f 277 {
14957cd0
A
278 ASSERT(virtualRegisterIndex < FirstConstantRegisterIndex);
279 return Address(base, (static_cast<unsigned>(virtualRegisterIndex) * sizeof(Register)) + OBJECT_OFFSETOF(JSValue, u.asBits.payload));
280 }
281
282 inline JSInterfaceJIT::Address JSInterfaceJIT::intPayloadFor(int virtualRegisterIndex, RegisterID base)
283 {
284 return payloadFor(virtualRegisterIndex, base);
285 }
286
287 inline JSInterfaceJIT::Address JSInterfaceJIT::intTagFor(int virtualRegisterIndex, RegisterID base)
288 {
289 return tagFor(virtualRegisterIndex, base);
4e4e5a6f
A
290 }
291
292 inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadDouble(unsigned virtualRegisterIndex, FPRegisterID dst, RegisterID scratch)
293 {
294 ASSERT(static_cast<int>(virtualRegisterIndex) < FirstConstantRegisterIndex);
295 loadPtr(tagFor(virtualRegisterIndex), scratch);
14957cd0
A
296 Jump isDouble = branch32(Below, scratch, TrustedImm32(JSValue::LowestTag));
297 Jump notInt = branch32(NotEqual, scratch, TrustedImm32(JSValue::Int32Tag));
4e4e5a6f
A
298 loadPtr(payloadFor(virtualRegisterIndex), scratch);
299 convertInt32ToDouble(scratch, dst);
300 Jump done = jump();
301 isDouble.link(this);
302 loadDouble(addressFor(virtualRegisterIndex), dst);
303 done.link(this);
304 return notInt;
6fe7ccc8
A
305 }
306
4e4e5a6f
A
307#endif
308
309#if USE(JSVALUE64)
93a37866
A
310 ALWAYS_INLINE JSInterfaceJIT::Jump JSInterfaceJIT::emitJumpIfNotJSCell(RegisterID reg)
311 {
312 return branchTest64(NonZero, reg, tagMaskRegister);
313 }
314
4e4e5a6f
A
315 ALWAYS_INLINE JSInterfaceJIT::Jump JSInterfaceJIT::emitJumpIfImmediateNumber(RegisterID reg)
316 {
93a37866 317 return branchTest64(NonZero, reg, tagTypeNumberRegister);
4e4e5a6f
A
318 }
319 ALWAYS_INLINE JSInterfaceJIT::Jump JSInterfaceJIT::emitJumpIfNotImmediateNumber(RegisterID reg)
320 {
93a37866 321 return branchTest64(Zero, reg, tagTypeNumberRegister);
4e4e5a6f
A
322 }
323 inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadJSCell(unsigned virtualRegisterIndex, RegisterID dst)
324 {
93a37866
A
325 load64(addressFor(virtualRegisterIndex), dst);
326 return branchTest64(NonZero, dst, tagMaskRegister);
4e4e5a6f
A
327 }
328
329 inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadInt32(unsigned virtualRegisterIndex, RegisterID dst)
330 {
93a37866
A
331 load64(addressFor(virtualRegisterIndex), dst);
332 Jump result = branch64(Below, dst, tagTypeNumberRegister);
4e4e5a6f
A
333 zeroExtend32ToPtr(dst, dst);
334 return result;
335 }
336
337 inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadDouble(unsigned virtualRegisterIndex, FPRegisterID dst, RegisterID scratch)
338 {
93a37866 339 load64(addressFor(virtualRegisterIndex), scratch);
4e4e5a6f 340 Jump notNumber = emitJumpIfNotImmediateNumber(scratch);
93a37866 341 Jump notInt = branch64(Below, scratch, tagTypeNumberRegister);
4e4e5a6f
A
342 convertInt32ToDouble(scratch, dst);
343 Jump done = jump();
344 notInt.link(this);
93a37866
A
345 add64(tagTypeNumberRegister, scratch);
346 move64ToDouble(scratch, dst);
4e4e5a6f
A
347 done.link(this);
348 return notNumber;
349 }
6fe7ccc8 350
4e4e5a6f
A
351 ALWAYS_INLINE void JSInterfaceJIT::emitFastArithImmToInt(RegisterID)
352 {
353 }
354
93a37866
A
355 // operand is int32_t, must have been zero-extended if register is 64-bit.
356 ALWAYS_INLINE void JSInterfaceJIT::emitFastArithIntToImmNoCheck(RegisterID src, RegisterID dest)
357 {
358 if (src != dest)
359 move(src, dest);
360 or64(tagTypeNumberRegister, dest);
361 }
4e4e5a6f
A
362#endif
363
14957cd0
A
364#if USE(JSVALUE64)
365 inline JSInterfaceJIT::Address JSInterfaceJIT::payloadFor(int virtualRegisterIndex, RegisterID base)
4e4e5a6f 366 {
14957cd0
A
367 ASSERT(virtualRegisterIndex < FirstConstantRegisterIndex);
368 return addressFor(virtualRegisterIndex, base);
4e4e5a6f
A
369 }
370
14957cd0 371 inline JSInterfaceJIT::Address JSInterfaceJIT::intPayloadFor(int virtualRegisterIndex, RegisterID base)
4e4e5a6f 372 {
14957cd0
A
373 ASSERT(virtualRegisterIndex < FirstConstantRegisterIndex);
374 return Address(base, (static_cast<unsigned>(virtualRegisterIndex) * sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
4e4e5a6f 375 }
14957cd0 376 inline JSInterfaceJIT::Address JSInterfaceJIT::intTagFor(int virtualRegisterIndex, RegisterID base)
4e4e5a6f 377 {
14957cd0
A
378 ASSERT(virtualRegisterIndex < FirstConstantRegisterIndex);
379 return Address(base, (static_cast<unsigned>(virtualRegisterIndex) * sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
4e4e5a6f
A
380 }
381#endif
382
93a37866
A
383 ALWAYS_INLINE JSInterfaceJIT::Jump JSInterfaceJIT::emitJumpIfNotType(RegisterID baseReg, RegisterID scratchReg, JSType type)
384 {
385 loadPtr(Address(baseReg, JSCell::structureOffset()), scratchReg);
386 return branch8(NotEqual, Address(scratchReg, Structure::typeInfoTypeOffset()), TrustedImm32(type));
387 }
388
389 ALWAYS_INLINE void JSInterfaceJIT::emitGetFromCallFrameHeaderPtr(JSStack::CallFrameHeaderEntry entry, RegisterID to, RegisterID from)
390 {
391 loadPtr(Address(from, entry * sizeof(Register)), to);
392 }
393
394 ALWAYS_INLINE void JSInterfaceJIT::emitPutToCallFrameHeader(RegisterID from, JSStack::CallFrameHeaderEntry entry)
395 {
396#if USE(JSVALUE32_64)
397 storePtr(from, payloadFor(entry, callFrameRegister));
398#else
399 store64(from, addressFor(entry, callFrameRegister));
400#endif
401 }
402
403 ALWAYS_INLINE void JSInterfaceJIT::emitPutImmediateToCallFrameHeader(void* value, JSStack::CallFrameHeaderEntry entry)
404 {
405 storePtr(TrustedImmPtr(value), Address(callFrameRegister, entry * sizeof(Register)));
406 }
407
408 ALWAYS_INLINE void JSInterfaceJIT::emitPutCellToCallFrameHeader(RegisterID from, JSStack::CallFrameHeaderEntry entry)
409 {
410#if USE(JSVALUE32_64)
411 store32(TrustedImm32(JSValue::CellTag), tagFor(entry, callFrameRegister));
412 store32(from, payloadFor(entry, callFrameRegister));
413#else
414 store64(from, addressFor(entry, callFrameRegister));
415#endif
416 }
417
14957cd0 418 inline JSInterfaceJIT::Address JSInterfaceJIT::addressFor(int virtualRegisterIndex, RegisterID base)
4e4e5a6f 419 {
14957cd0
A
420 ASSERT(virtualRegisterIndex < FirstConstantRegisterIndex);
421 return Address(base, (static_cast<unsigned>(virtualRegisterIndex) * sizeof(Register)));
4e4e5a6f
A
422 }
423
93a37866
A
424#if CPU(ARM) || CPU(ARM64)
425
426 ALWAYS_INLINE void JSInterfaceJIT::preserveReturnAddressAfterCall(RegisterID reg)
427 {
428 move(linkRegister, reg);
429 }
430
431 ALWAYS_INLINE void JSInterfaceJIT::restoreReturnAddressBeforeReturn(RegisterID reg)
432 {
433 move(reg, linkRegister);
434 }
435
436 ALWAYS_INLINE void JSInterfaceJIT::restoreReturnAddressBeforeReturn(Address address)
437 {
438 loadPtr(address, linkRegister);
439 }
440#elif CPU(SH4)
441
442 ALWAYS_INLINE void JSInterfaceJIT::preserveReturnAddressAfterCall(RegisterID reg)
443 {
444 m_assembler.stspr(reg);
445 }
446
447 ALWAYS_INLINE void JSInterfaceJIT::restoreReturnAddressBeforeReturn(RegisterID reg)
448 {
449 m_assembler.ldspr(reg);
450 }
451
452 ALWAYS_INLINE void JSInterfaceJIT::restoreReturnAddressBeforeReturn(Address address)
453 {
454 loadPtrLinkReg(address);
455 }
456
457#elif CPU(MIPS)
458
459 ALWAYS_INLINE void JSInterfaceJIT::preserveReturnAddressAfterCall(RegisterID reg)
460 {
461 move(returnAddressRegister, reg);
462 }
463
464 ALWAYS_INLINE void JSInterfaceJIT::restoreReturnAddressBeforeReturn(RegisterID reg)
465 {
466 move(reg, returnAddressRegister);
467 }
468
469 ALWAYS_INLINE void JSInterfaceJIT::restoreReturnAddressBeforeReturn(Address address)
470 {
471 loadPtr(address, returnAddressRegister);
472 }
473
474#else // CPU(X86) || CPU(X86_64)
475
476 ALWAYS_INLINE void JSInterfaceJIT::preserveReturnAddressAfterCall(RegisterID reg)
477 {
478 pop(reg);
479 }
480
481 ALWAYS_INLINE void JSInterfaceJIT::restoreReturnAddressBeforeReturn(RegisterID reg)
482 {
483 push(reg);
484 }
485
486 ALWAYS_INLINE void JSInterfaceJIT::restoreReturnAddressBeforeReturn(Address address)
487 {
488 push(address);
489 }
490
491#endif
492
493 ALWAYS_INLINE void JSInterfaceJIT::restoreArgumentReference()
494 {
495 move(stackPointerRegister, firstArgumentRegister);
496 poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
497 }
498
499} // namespace JSC
500
501#endif // ENABLE(JIT)
4e4e5a6f
A
502
503#endif // JSInterfaceJIT_h