JSInterfaceJIT.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  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. #ifndef JSInterfaceJIT_h
  26. #define JSInterfaceJIT_h
  27. #include "BytecodeConventions.h"
  28. #include "JITCode.h"
  29. #include "JITStubs.h"
  30. #include "JSCJSValue.h"
  31. #include "JSStack.h"
  32. #include "JSString.h"
  33. #include "MacroAssembler.h"
  34. #include <wtf/Vector.h>
  35. #if ENABLE(JIT)
  36. namespace JSC {
  37. class JSInterfaceJIT : public MacroAssembler {
  38. public:
  39. // NOTES:
  40. //
  41. // regT0 has two special meanings. The return value from a stub
  42. // call will always be in regT0, and by default (unless
  43. // a register is specified) emitPutVirtualRegister() will store
  44. // the value from regT0.
  45. //
  46. // regT3 is required to be callee-preserved.
  47. //
  48. // tempRegister2 is has no such dependencies. It is important that
  49. // on x86/x86-64 it is ecx for performance reasons, since the
  50. // MacroAssembler will need to plant register swaps if it is not -
  51. // however the code will still function correctly.
  52. #if CPU(X86_64)
  53. static const RegisterID returnValueRegister = X86Registers::eax;
  54. static const RegisterID cachedResultRegister = X86Registers::eax;
  55. #if !OS(WINDOWS)
  56. static const RegisterID firstArgumentRegister = X86Registers::edi;
  57. #else
  58. static const RegisterID firstArgumentRegister = X86Registers::ecx;
  59. #endif
  60. #if ENABLE(VALUE_PROFILER)
  61. static const RegisterID bucketCounterRegister = X86Registers::r10;
  62. #endif
  63. static const RegisterID callFrameRegister = X86Registers::r13;
  64. static const RegisterID tagTypeNumberRegister = X86Registers::r14;
  65. static const RegisterID tagMaskRegister = X86Registers::r15;
  66. static const RegisterID regT0 = X86Registers::eax;
  67. static const RegisterID regT1 = X86Registers::edx;
  68. static const RegisterID regT2 = X86Registers::ecx;
  69. static const RegisterID regT3 = X86Registers::ebx;
  70. static const FPRegisterID fpRegT0 = X86Registers::xmm0;
  71. static const FPRegisterID fpRegT1 = X86Registers::xmm1;
  72. static const FPRegisterID fpRegT2 = X86Registers::xmm2;
  73. static const FPRegisterID fpRegT3 = X86Registers::xmm3;
  74. static const RegisterID nonArgGPR1 = X86Registers::eax; // regT0
  75. #elif CPU(X86)
  76. static const RegisterID returnValueRegister = X86Registers::eax;
  77. static const RegisterID cachedResultRegister = X86Registers::eax;
  78. // On x86 we always use fastcall conventions = but on
  79. // OS X if might make more sense to just use regparm.
  80. static const RegisterID firstArgumentRegister = X86Registers::ecx;
  81. static const RegisterID bucketCounterRegister = X86Registers::esi;
  82. static const RegisterID callFrameRegister = X86Registers::edi;
  83. static const RegisterID regT0 = X86Registers::eax;
  84. static const RegisterID regT1 = X86Registers::edx;
  85. static const RegisterID regT2 = X86Registers::ecx;
  86. static const RegisterID regT3 = X86Registers::ebx;
  87. static const FPRegisterID fpRegT0 = X86Registers::xmm0;
  88. static const FPRegisterID fpRegT1 = X86Registers::xmm1;
  89. static const FPRegisterID fpRegT2 = X86Registers::xmm2;
  90. static const FPRegisterID fpRegT3 = X86Registers::xmm3;
  91. #elif CPU(ARM)
  92. static const RegisterID returnValueRegister = ARMRegisters::r0;
  93. static const RegisterID cachedResultRegister = ARMRegisters::r0;
  94. static const RegisterID firstArgumentRegister = ARMRegisters::r0;
  95. #if ENABLE(VALUE_PROFILER)
  96. static const RegisterID bucketCounterRegister = ARMRegisters::r7;
  97. #endif
  98. static const RegisterID regT0 = ARMRegisters::r0;
  99. static const RegisterID regT1 = ARMRegisters::r1;
  100. static const RegisterID regT2 = ARMRegisters::r2;
  101. static const RegisterID regT3 = ARMRegisters::r4;
  102. // Update ctiTrampoline in JITStubs.cpp if these values are changed!
  103. static const RegisterID callFrameRegister = ARMRegisters::r5;
  104. static const FPRegisterID fpRegT0 = ARMRegisters::d0;
  105. static const FPRegisterID fpRegT1 = ARMRegisters::d1;
  106. static const FPRegisterID fpRegT2 = ARMRegisters::d2;
  107. static const FPRegisterID fpRegT3 = ARMRegisters::d3;
  108. #elif CPU(MIPS)
  109. static const RegisterID returnValueRegister = MIPSRegisters::v0;
  110. static const RegisterID cachedResultRegister = MIPSRegisters::v0;
  111. static const RegisterID firstArgumentRegister = MIPSRegisters::a0;
  112. #if ENABLE(VALUE_PROFILER)
  113. static const RegisterID bucketCounterRegister = MIPSRegisters::s3;
  114. #endif
  115. // regT0 must be v0 for returning a 32-bit value.
  116. static const RegisterID regT0 = MIPSRegisters::v0;
  117. // regT1 must be v1 for returning a pair of 32-bit value.
  118. static const RegisterID regT1 = MIPSRegisters::v1;
  119. static const RegisterID regT2 = MIPSRegisters::t4;
  120. // regT3 must be saved in the callee, so use an S register.
  121. static const RegisterID regT3 = MIPSRegisters::s2;
  122. static const RegisterID callFrameRegister = MIPSRegisters::s0;
  123. static const FPRegisterID fpRegT0 = MIPSRegisters::f4;
  124. static const FPRegisterID fpRegT1 = MIPSRegisters::f6;
  125. static const FPRegisterID fpRegT2 = MIPSRegisters::f8;
  126. static const FPRegisterID fpRegT3 = MIPSRegisters::f10;
  127. #elif CPU(SH4)
  128. static const RegisterID callFrameRegister = SH4Registers::fp;
  129. static const RegisterID regT0 = SH4Registers::r0;
  130. static const RegisterID regT1 = SH4Registers::r1;
  131. static const RegisterID regT2 = SH4Registers::r2;
  132. static const RegisterID regT3 = SH4Registers::r10;
  133. static const RegisterID regT4 = SH4Registers::r4;
  134. static const RegisterID regT5 = SH4Registers::r5;
  135. static const RegisterID regT6 = SH4Registers::r6;
  136. static const RegisterID regT7 = SH4Registers::r7;
  137. static const RegisterID firstArgumentRegister =regT4;
  138. static const RegisterID returnValueRegister = SH4Registers::r0;
  139. static const RegisterID cachedResultRegister = SH4Registers::r0;
  140. static const FPRegisterID fpRegT0 = SH4Registers::fr0;
  141. static const FPRegisterID fpRegT1 = SH4Registers::fr2;
  142. static const FPRegisterID fpRegT2 = SH4Registers::fr4;
  143. static const FPRegisterID fpRegT3 = SH4Registers::fr6;
  144. static const FPRegisterID fpRegT4 = SH4Registers::fr8;
  145. static const FPRegisterID fpRegT5 = SH4Registers::fr10;
  146. static const FPRegisterID fpRegT6 = SH4Registers::fr12;
  147. static const FPRegisterID fpRegT7 = SH4Registers::fr14;
  148. #else
  149. #error "JIT not supported on this platform."
  150. #endif
  151. #if USE(JSVALUE32_64)
  152. // Can't just propogate JSValue::Int32Tag as visual studio doesn't like it
  153. static const unsigned Int32Tag = 0xffffffff;
  154. COMPILE_ASSERT(Int32Tag == JSValue::Int32Tag, Int32Tag_out_of_sync);
  155. #else
  156. static const unsigned Int32Tag = TagTypeNumber >> 32;
  157. #endif
  158. inline Jump emitLoadJSCell(unsigned virtualRegisterIndex, RegisterID payload);
  159. inline Jump emitLoadInt32(unsigned virtualRegisterIndex, RegisterID dst);
  160. inline Jump emitLoadDouble(unsigned virtualRegisterIndex, FPRegisterID dst, RegisterID scratch);
  161. #if USE(JSVALUE32_64)
  162. inline Jump emitJumpIfNotJSCell(unsigned virtualRegisterIndex);
  163. inline Address tagFor(int index, RegisterID base = callFrameRegister);
  164. #endif
  165. #if USE(JSVALUE64)
  166. Jump emitJumpIfNotJSCell(RegisterID);
  167. Jump emitJumpIfImmediateNumber(RegisterID reg);
  168. Jump emitJumpIfNotImmediateNumber(RegisterID reg);
  169. void emitFastArithImmToInt(RegisterID reg);
  170. void emitFastArithIntToImmNoCheck(RegisterID src, RegisterID dest);
  171. #endif
  172. Jump emitJumpIfNotType(RegisterID baseReg, RegisterID scratchReg, JSType);
  173. void emitGetFromCallFrameHeaderPtr(JSStack::CallFrameHeaderEntry, RegisterID to, RegisterID from = callFrameRegister);
  174. void emitPutToCallFrameHeader(RegisterID from, JSStack::CallFrameHeaderEntry);
  175. void emitPutImmediateToCallFrameHeader(void* value, JSStack::CallFrameHeaderEntry);
  176. void emitPutCellToCallFrameHeader(RegisterID from, JSStack::CallFrameHeaderEntry);
  177. void preserveReturnAddressAfterCall(RegisterID);
  178. void restoreReturnAddressBeforeReturn(RegisterID);
  179. void restoreReturnAddressBeforeReturn(Address);
  180. void restoreArgumentReference();
  181. inline Address payloadFor(int index, RegisterID base = callFrameRegister);
  182. inline Address intPayloadFor(int index, RegisterID base = callFrameRegister);
  183. inline Address intTagFor(int index, RegisterID base = callFrameRegister);
  184. inline Address addressFor(int index, RegisterID base = callFrameRegister);
  185. };
  186. struct ThunkHelpers {
  187. static unsigned jsStringLengthOffset() { return OBJECT_OFFSETOF(JSString, m_length); }
  188. static unsigned jsStringValueOffset() { return OBJECT_OFFSETOF(JSString, m_value); }
  189. };
  190. #if USE(JSVALUE32_64)
  191. inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadJSCell(unsigned virtualRegisterIndex, RegisterID payload)
  192. {
  193. loadPtr(payloadFor(virtualRegisterIndex), payload);
  194. return emitJumpIfNotJSCell(virtualRegisterIndex);
  195. }
  196. inline JSInterfaceJIT::Jump JSInterfaceJIT::emitJumpIfNotJSCell(unsigned virtualRegisterIndex)
  197. {
  198. ASSERT(static_cast<int>(virtualRegisterIndex) < FirstConstantRegisterIndex);
  199. return branch32(NotEqual, tagFor(virtualRegisterIndex), TrustedImm32(JSValue::CellTag));
  200. }
  201. inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadInt32(unsigned virtualRegisterIndex, RegisterID dst)
  202. {
  203. ASSERT(static_cast<int>(virtualRegisterIndex) < FirstConstantRegisterIndex);
  204. loadPtr(payloadFor(virtualRegisterIndex), dst);
  205. return branch32(NotEqual, tagFor(static_cast<int>(virtualRegisterIndex)), TrustedImm32(JSValue::Int32Tag));
  206. }
  207. inline JSInterfaceJIT::Address JSInterfaceJIT::tagFor(int virtualRegisterIndex, RegisterID base)
  208. {
  209. ASSERT(virtualRegisterIndex < FirstConstantRegisterIndex);
  210. return Address(base, (static_cast<unsigned>(virtualRegisterIndex) * sizeof(Register)) + OBJECT_OFFSETOF(JSValue, u.asBits.tag));
  211. }
  212. inline JSInterfaceJIT::Address JSInterfaceJIT::payloadFor(int virtualRegisterIndex, RegisterID base)
  213. {
  214. ASSERT(virtualRegisterIndex < FirstConstantRegisterIndex);
  215. return Address(base, (static_cast<unsigned>(virtualRegisterIndex) * sizeof(Register)) + OBJECT_OFFSETOF(JSValue, u.asBits.payload));
  216. }
  217. inline JSInterfaceJIT::Address JSInterfaceJIT::intPayloadFor(int virtualRegisterIndex, RegisterID base)
  218. {
  219. return payloadFor(virtualRegisterIndex, base);
  220. }
  221. inline JSInterfaceJIT::Address JSInterfaceJIT::intTagFor(int virtualRegisterIndex, RegisterID base)
  222. {
  223. return tagFor(virtualRegisterIndex, base);
  224. }
  225. inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadDouble(unsigned virtualRegisterIndex, FPRegisterID dst, RegisterID scratch)
  226. {
  227. ASSERT(static_cast<int>(virtualRegisterIndex) < FirstConstantRegisterIndex);
  228. loadPtr(tagFor(virtualRegisterIndex), scratch);
  229. Jump isDouble = branch32(Below, scratch, TrustedImm32(JSValue::LowestTag));
  230. Jump notInt = branch32(NotEqual, scratch, TrustedImm32(JSValue::Int32Tag));
  231. loadPtr(payloadFor(virtualRegisterIndex), scratch);
  232. convertInt32ToDouble(scratch, dst);
  233. Jump done = jump();
  234. isDouble.link(this);
  235. loadDouble(addressFor(virtualRegisterIndex), dst);
  236. done.link(this);
  237. return notInt;
  238. }
  239. #endif
  240. #if USE(JSVALUE64)
  241. ALWAYS_INLINE JSInterfaceJIT::Jump JSInterfaceJIT::emitJumpIfNotJSCell(RegisterID reg)
  242. {
  243. return branchTest64(NonZero, reg, tagMaskRegister);
  244. }
  245. ALWAYS_INLINE JSInterfaceJIT::Jump JSInterfaceJIT::emitJumpIfImmediateNumber(RegisterID reg)
  246. {
  247. return branchTest64(NonZero, reg, tagTypeNumberRegister);
  248. }
  249. ALWAYS_INLINE JSInterfaceJIT::Jump JSInterfaceJIT::emitJumpIfNotImmediateNumber(RegisterID reg)
  250. {
  251. return branchTest64(Zero, reg, tagTypeNumberRegister);
  252. }
  253. inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadJSCell(unsigned virtualRegisterIndex, RegisterID dst)
  254. {
  255. load64(addressFor(virtualRegisterIndex), dst);
  256. return branchTest64(NonZero, dst, tagMaskRegister);
  257. }
  258. inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadInt32(unsigned virtualRegisterIndex, RegisterID dst)
  259. {
  260. load64(addressFor(virtualRegisterIndex), dst);
  261. Jump result = branch64(Below, dst, tagTypeNumberRegister);
  262. zeroExtend32ToPtr(dst, dst);
  263. return result;
  264. }
  265. inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadDouble(unsigned virtualRegisterIndex, FPRegisterID dst, RegisterID scratch)
  266. {
  267. load64(addressFor(virtualRegisterIndex), scratch);
  268. Jump notNumber = emitJumpIfNotImmediateNumber(scratch);
  269. Jump notInt = branch64(Below, scratch, tagTypeNumberRegister);
  270. convertInt32ToDouble(scratch, dst);
  271. Jump done = jump();
  272. notInt.link(this);
  273. add64(tagTypeNumberRegister, scratch);
  274. move64ToDouble(scratch, dst);
  275. done.link(this);
  276. return notNumber;
  277. }
  278. ALWAYS_INLINE void JSInterfaceJIT::emitFastArithImmToInt(RegisterID)
  279. {
  280. }
  281. // operand is int32_t, must have been zero-extended if register is 64-bit.
  282. ALWAYS_INLINE void JSInterfaceJIT::emitFastArithIntToImmNoCheck(RegisterID src, RegisterID dest)
  283. {
  284. if (src != dest)
  285. move(src, dest);
  286. or64(tagTypeNumberRegister, dest);
  287. }
  288. #endif
  289. #if USE(JSVALUE64)
  290. inline JSInterfaceJIT::Address JSInterfaceJIT::payloadFor(int virtualRegisterIndex, RegisterID base)
  291. {
  292. ASSERT(virtualRegisterIndex < FirstConstantRegisterIndex);
  293. return addressFor(virtualRegisterIndex, base);
  294. }
  295. inline JSInterfaceJIT::Address JSInterfaceJIT::intPayloadFor(int virtualRegisterIndex, RegisterID base)
  296. {
  297. ASSERT(virtualRegisterIndex < FirstConstantRegisterIndex);
  298. return Address(base, (static_cast<unsigned>(virtualRegisterIndex) * sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
  299. }
  300. inline JSInterfaceJIT::Address JSInterfaceJIT::intTagFor(int virtualRegisterIndex, RegisterID base)
  301. {
  302. ASSERT(virtualRegisterIndex < FirstConstantRegisterIndex);
  303. return Address(base, (static_cast<unsigned>(virtualRegisterIndex) * sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
  304. }
  305. #endif
  306. ALWAYS_INLINE JSInterfaceJIT::Jump JSInterfaceJIT::emitJumpIfNotType(RegisterID baseReg, RegisterID scratchReg, JSType type)
  307. {
  308. loadPtr(Address(baseReg, JSCell::structureOffset()), scratchReg);
  309. return branch8(NotEqual, Address(scratchReg, Structure::typeInfoTypeOffset()), TrustedImm32(type));
  310. }
  311. ALWAYS_INLINE void JSInterfaceJIT::emitGetFromCallFrameHeaderPtr(JSStack::CallFrameHeaderEntry entry, RegisterID to, RegisterID from)
  312. {
  313. loadPtr(Address(from, entry * sizeof(Register)), to);
  314. }
  315. ALWAYS_INLINE void JSInterfaceJIT::emitPutToCallFrameHeader(RegisterID from, JSStack::CallFrameHeaderEntry entry)
  316. {
  317. #if USE(JSVALUE32_64)
  318. storePtr(from, payloadFor(entry, callFrameRegister));
  319. #else
  320. store64(from, addressFor(entry, callFrameRegister));
  321. #endif
  322. }
  323. ALWAYS_INLINE void JSInterfaceJIT::emitPutImmediateToCallFrameHeader(void* value, JSStack::CallFrameHeaderEntry entry)
  324. {
  325. storePtr(TrustedImmPtr(value), Address(callFrameRegister, entry * sizeof(Register)));
  326. }
  327. ALWAYS_INLINE void JSInterfaceJIT::emitPutCellToCallFrameHeader(RegisterID from, JSStack::CallFrameHeaderEntry entry)
  328. {
  329. #if USE(JSVALUE32_64)
  330. store32(TrustedImm32(JSValue::CellTag), tagFor(entry, callFrameRegister));
  331. store32(from, payloadFor(entry, callFrameRegister));
  332. #else
  333. store64(from, addressFor(entry, callFrameRegister));
  334. #endif
  335. }
  336. inline JSInterfaceJIT::Address JSInterfaceJIT::addressFor(int virtualRegisterIndex, RegisterID base)
  337. {
  338. ASSERT(virtualRegisterIndex < FirstConstantRegisterIndex);
  339. return Address(base, (static_cast<unsigned>(virtualRegisterIndex) * sizeof(Register)));
  340. }
  341. #if CPU(ARM)
  342. ALWAYS_INLINE void JSInterfaceJIT::preserveReturnAddressAfterCall(RegisterID reg)
  343. {
  344. move(linkRegister, reg);
  345. }
  346. ALWAYS_INLINE void JSInterfaceJIT::restoreReturnAddressBeforeReturn(RegisterID reg)
  347. {
  348. move(reg, linkRegister);
  349. }
  350. ALWAYS_INLINE void JSInterfaceJIT::restoreReturnAddressBeforeReturn(Address address)
  351. {
  352. loadPtr(address, linkRegister);
  353. }
  354. #elif CPU(SH4)
  355. ALWAYS_INLINE void JSInterfaceJIT::preserveReturnAddressAfterCall(RegisterID reg)
  356. {
  357. m_assembler.stspr(reg);
  358. }
  359. ALWAYS_INLINE void JSInterfaceJIT::restoreReturnAddressBeforeReturn(RegisterID reg)
  360. {
  361. m_assembler.ldspr(reg);
  362. }
  363. ALWAYS_INLINE void JSInterfaceJIT::restoreReturnAddressBeforeReturn(Address address)
  364. {
  365. loadPtrLinkReg(address);
  366. }
  367. #elif CPU(MIPS)
  368. ALWAYS_INLINE void JSInterfaceJIT::preserveReturnAddressAfterCall(RegisterID reg)
  369. {
  370. move(returnAddressRegister, reg);
  371. }
  372. ALWAYS_INLINE void JSInterfaceJIT::restoreReturnAddressBeforeReturn(RegisterID reg)
  373. {
  374. move(reg, returnAddressRegister);
  375. }
  376. ALWAYS_INLINE void JSInterfaceJIT::restoreReturnAddressBeforeReturn(Address address)
  377. {
  378. loadPtr(address, returnAddressRegister);
  379. }
  380. #else // CPU(X86) || CPU(X86_64)
  381. ALWAYS_INLINE void JSInterfaceJIT::preserveReturnAddressAfterCall(RegisterID reg)
  382. {
  383. pop(reg);
  384. }
  385. ALWAYS_INLINE void JSInterfaceJIT::restoreReturnAddressBeforeReturn(RegisterID reg)
  386. {
  387. push(reg);
  388. }
  389. ALWAYS_INLINE void JSInterfaceJIT::restoreReturnAddressBeforeReturn(Address address)
  390. {
  391. push(address);
  392. }
  393. #endif
  394. ALWAYS_INLINE void JSInterfaceJIT::restoreArgumentReference()
  395. {
  396. move(stackPointerRegister, firstArgumentRegister);
  397. poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
  398. }
  399. } // namespace JSC
  400. #endif // ENABLE(JIT)
  401. #endif // JSInterfaceJIT_h