JITStubCall.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  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. #ifndef JITStubCall_h
  26. #define JITStubCall_h
  27. #include "MacroAssemblerCodeRef.h"
  28. #if ENABLE(JIT)
  29. namespace JSC {
  30. class JITStubCall {
  31. public:
  32. JITStubCall(JIT* jit, JSObject* (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
  33. : m_jit(jit)
  34. , m_stub(stub)
  35. #if USE(JSVALUE32_64) || !ASSERT_DISABLED
  36. , m_returnType(Cell)
  37. #endif
  38. , m_stackIndex(JITSTACKFRAME_ARGS_INDEX)
  39. {
  40. }
  41. JITStubCall(JIT* jit, JSPropertyNameIterator* (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
  42. : m_jit(jit)
  43. , m_stub(stub)
  44. #if USE(JSVALUE32_64) || !ASSERT_DISABLED
  45. , m_returnType(Cell)
  46. #endif
  47. , m_stackIndex(JITSTACKFRAME_ARGS_INDEX)
  48. {
  49. }
  50. JITStubCall(JIT* jit, void* (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
  51. : m_jit(jit)
  52. , m_stub(stub)
  53. #if USE(JSVALUE32_64) || !ASSERT_DISABLED
  54. , m_returnType(VoidPtr)
  55. #endif
  56. , m_stackIndex(JITSTACKFRAME_ARGS_INDEX)
  57. {
  58. }
  59. JITStubCall(JIT* jit, int (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
  60. : m_jit(jit)
  61. , m_stub(stub)
  62. #if USE(JSVALUE32_64) || !ASSERT_DISABLED
  63. , m_returnType(Int)
  64. #endif
  65. , m_stackIndex(JITSTACKFRAME_ARGS_INDEX)
  66. {
  67. }
  68. JITStubCall(JIT* jit, bool (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
  69. : m_jit(jit)
  70. , m_stub(stub)
  71. #if USE(JSVALUE32_64) || !ASSERT_DISABLED
  72. , m_returnType(Int)
  73. #endif
  74. , m_stackIndex(JITSTACKFRAME_ARGS_INDEX)
  75. {
  76. }
  77. JITStubCall(JIT* jit, void (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
  78. : m_jit(jit)
  79. , m_stub(stub)
  80. #if USE(JSVALUE32_64) || !ASSERT_DISABLED
  81. , m_returnType(Void)
  82. #endif
  83. , m_stackIndex(JITSTACKFRAME_ARGS_INDEX)
  84. {
  85. }
  86. JITStubCall(JIT* jit, EncodedJSValue (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
  87. : m_jit(jit)
  88. , m_stub(stub)
  89. #if USE(JSVALUE32_64) || !ASSERT_DISABLED
  90. , m_returnType(Value)
  91. #endif
  92. , m_stackIndex(JITSTACKFRAME_ARGS_INDEX)
  93. {
  94. }
  95. #if ENABLE(DETACHED_JIT) && BUILDING_DETACHED_JIT
  96. JITStubCall(JIT* jit, RemoteFunctionReturningVoidPtr stub)
  97. : m_jit(jit)
  98. , m_stub(stub)
  99. #if USE(JSVALUE32_64) || !ASSERT_DISABLED
  100. , m_returnType(VoidPtr)
  101. #endif
  102. , m_stackIndex(JITSTACKFRAME_ARGS_INDEX)
  103. {
  104. }
  105. #endif
  106. // Arguments are added first to last.
  107. void skipArgument()
  108. {
  109. m_stackIndex += stackIndexStep;
  110. }
  111. void addArgument(JIT::TrustedImm32 argument)
  112. {
  113. m_jit->poke(argument, m_stackIndex);
  114. m_stackIndex += stackIndexStep;
  115. }
  116. void addArgument(JIT::Imm32 argument)
  117. {
  118. m_jit->poke(argument, m_stackIndex);
  119. m_stackIndex += stackIndexStep;
  120. }
  121. void addArgument(JIT::TrustedImmPtr argument)
  122. {
  123. m_jit->poke(argument, m_stackIndex);
  124. m_stackIndex += stackIndexStep;
  125. }
  126. void addArgument(JIT::ImmPtr argument)
  127. {
  128. m_jit->poke(argument, m_stackIndex);
  129. m_stackIndex += stackIndexStep;
  130. }
  131. void addArgument(JIT::RegisterID argument)
  132. {
  133. #if USE(JSVALUE32_64)
  134. m_jit->poke(argument, m_stackIndex);
  135. #else
  136. m_jit->poke64(argument, m_stackIndex);
  137. #endif
  138. m_stackIndex += stackIndexStep;
  139. }
  140. #if USE(JSVALUE32_64)
  141. void addArgument(const JSValue& value)
  142. {
  143. m_jit->poke(JIT::Imm32(value.payload()), m_stackIndex);
  144. m_jit->poke(JIT::Imm32(value.tag()), m_stackIndex + 1);
  145. m_stackIndex += stackIndexStep;
  146. }
  147. #else
  148. void addArgument(JIT::TrustedImm64 argument)
  149. {
  150. m_jit->poke(argument, m_stackIndex);
  151. m_stackIndex += stackIndexStep;
  152. }
  153. void addArgument(JIT::Imm64 argument)
  154. {
  155. m_jit->poke(argument, m_stackIndex);
  156. m_stackIndex += stackIndexStep;
  157. }
  158. #endif
  159. void addArgument(JIT::RegisterID tag, JIT::RegisterID payload)
  160. {
  161. m_jit->poke(payload, m_stackIndex);
  162. m_jit->poke(tag, m_stackIndex + 1);
  163. m_stackIndex += stackIndexStep;
  164. }
  165. #if USE(JSVALUE32_64)
  166. void addArgument(unsigned srcVirtualRegister)
  167. {
  168. if (m_jit->m_codeBlock->isConstantRegisterIndex(srcVirtualRegister)) {
  169. addArgument(m_jit->getConstantOperand(srcVirtualRegister));
  170. return;
  171. }
  172. m_jit->emitLoad(srcVirtualRegister, JIT::regT1, JIT::regT0);
  173. addArgument(JIT::regT1, JIT::regT0);
  174. }
  175. void getArgument(size_t argumentNumber, JIT::RegisterID tag, JIT::RegisterID payload)
  176. {
  177. size_t stackIndex = JITSTACKFRAME_ARGS_INDEX + (argumentNumber * stackIndexStep);
  178. m_jit->peek(payload, stackIndex);
  179. m_jit->peek(tag, stackIndex + 1);
  180. }
  181. #else
  182. void addArgument(unsigned src, JIT::RegisterID scratchRegister) // src is a virtual register.
  183. {
  184. if (m_jit->m_codeBlock->isConstantRegisterIndex(src))
  185. addArgument(JIT::Imm64(JSValue::encode(m_jit->m_codeBlock->getConstant(src))));
  186. else {
  187. m_jit->load64(JIT::Address(JIT::callFrameRegister, src * sizeof(Register)), scratchRegister);
  188. addArgument(scratchRegister);
  189. }
  190. m_jit->killLastResultRegister();
  191. }
  192. #endif
  193. JIT::Call call()
  194. {
  195. #if ENABLE(OPCODE_SAMPLING)
  196. if (m_jit->m_bytecodeOffset != (unsigned)-1)
  197. m_jit->sampleInstruction(m_jit->m_codeBlock->instructions().begin() + m_jit->m_bytecodeOffset, true);
  198. #endif
  199. m_jit->restoreArgumentReference();
  200. m_jit->updateTopCallFrame();
  201. JIT::Call call = m_jit->call();
  202. m_jit->m_calls.append(CallRecord(call, m_jit->m_bytecodeOffset, m_stub.value()));
  203. #if ENABLE(OPCODE_SAMPLING)
  204. if (m_jit->m_bytecodeOffset != (unsigned)-1)
  205. m_jit->sampleInstruction(m_jit->m_codeBlock->instructions().begin() + m_jit->m_bytecodeOffset, false);
  206. #endif
  207. #if USE(JSVALUE32_64)
  208. m_jit->unmap();
  209. #else
  210. m_jit->killLastResultRegister();
  211. #endif
  212. return call;
  213. }
  214. #if USE(JSVALUE32_64)
  215. JIT::Call call(unsigned dst) // dst is a virtual register.
  216. {
  217. ASSERT(m_returnType == Value || m_returnType == Cell);
  218. JIT::Call call = this->call();
  219. if (m_returnType == Value)
  220. m_jit->emitStore(dst, JIT::regT1, JIT::regT0);
  221. else
  222. m_jit->emitStoreCell(dst, JIT::returnValueRegister);
  223. return call;
  224. }
  225. JIT::Call callWithValueProfiling(unsigned dst)
  226. {
  227. ASSERT(m_returnType == Value || m_returnType == Cell);
  228. JIT::Call call = this->call();
  229. ASSERT(JIT::returnValueRegister == JIT::regT0);
  230. if (m_returnType == Cell)
  231. m_jit->move(JIT::TrustedImm32(JSValue::CellTag), JIT::regT1);
  232. m_jit->emitValueProfilingSite();
  233. if (m_returnType == Value)
  234. m_jit->emitStore(dst, JIT::regT1, JIT::regT0);
  235. else
  236. m_jit->emitStoreCell(dst, JIT::returnValueRegister);
  237. return call;
  238. }
  239. #else
  240. JIT::Call call(unsigned dst) // dst is a virtual register.
  241. {
  242. ASSERT(m_returnType == Value || m_returnType == Cell);
  243. JIT::Call call = this->call();
  244. m_jit->emitPutVirtualRegister(dst);
  245. return call;
  246. }
  247. JIT::Call callWithValueProfiling(unsigned dst)
  248. {
  249. ASSERT(m_returnType == Value || m_returnType == Cell);
  250. JIT::Call call = this->call();
  251. ASSERT(JIT::returnValueRegister == JIT::regT0);
  252. m_jit->emitValueProfilingSite();
  253. m_jit->emitPutVirtualRegister(dst);
  254. return call;
  255. }
  256. #endif
  257. JIT::Call call(JIT::RegisterID dst) // dst is a machine register.
  258. {
  259. #if USE(JSVALUE32_64) || !ASSERT_DISABLED
  260. ASSERT(m_returnType == Value || m_returnType == VoidPtr || m_returnType == Int || m_returnType == Cell);
  261. #endif
  262. JIT::Call call = this->call();
  263. if (dst != JIT::returnValueRegister)
  264. m_jit->move(JIT::returnValueRegister, dst);
  265. return call;
  266. }
  267. private:
  268. static const size_t stackIndexStep = sizeof(EncodedJSValue) == 2 * sizeof(void*) ? 2 : 1;
  269. JIT* m_jit;
  270. FunctionPtr m_stub;
  271. #if USE(JSVALUE32_64) || !ASSERT_DISABLED
  272. enum { Void, VoidPtr, Int, Value, Cell } m_returnType;
  273. #endif
  274. size_t m_stackIndex;
  275. };
  276. }
  277. #endif // ENABLE(JIT)
  278. #endif // JITStubCall_h