DFGSlowPathGenerator.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. /*
  2. * Copyright (C) 2012 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 DFGSlowPathGenerator_h
  26. #define DFGSlowPathGenerator_h
  27. #include <wtf/Platform.h>
  28. #if ENABLE(DFG_JIT)
  29. #include "DFGCommon.h"
  30. #include "DFGSilentRegisterSavePlan.h"
  31. #include "DFGSpeculativeJIT.h"
  32. #include <wtf/FastAllocBase.h>
  33. #include <wtf/PassOwnPtr.h>
  34. namespace JSC { namespace DFG {
  35. class SlowPathGenerator {
  36. WTF_MAKE_FAST_ALLOCATED;
  37. public:
  38. SlowPathGenerator(SpeculativeJIT* jit)
  39. : m_currentNode(jit->m_currentNode)
  40. {
  41. }
  42. virtual ~SlowPathGenerator() { }
  43. void generate(SpeculativeJIT* jit)
  44. {
  45. #if DFG_ENABLE(DEBUG_VERBOSE)
  46. dataLogF("Generating slow path %p at offset 0x%x\n", this, jit->m_jit.debugOffset());
  47. #endif
  48. m_label = jit->m_jit.label();
  49. jit->m_currentNode = m_currentNode;
  50. generateInternal(jit);
  51. #if !ASSERT_DISABLED
  52. jit->m_jit.breakpoint(); // make sure that the generator jumps back to somewhere
  53. #endif
  54. }
  55. MacroAssembler::Label label() const { return m_label; }
  56. virtual MacroAssembler::Call call() const
  57. {
  58. RELEASE_ASSERT_NOT_REACHED(); // By default slow path generators don't have a call.
  59. return MacroAssembler::Call();
  60. }
  61. protected:
  62. virtual void generateInternal(SpeculativeJIT*) = 0;
  63. MacroAssembler::Label m_label;
  64. Node* m_currentNode;
  65. };
  66. template<typename JumpType>
  67. class JumpingSlowPathGenerator : public SlowPathGenerator {
  68. public:
  69. JumpingSlowPathGenerator(JumpType from, SpeculativeJIT* jit)
  70. : SlowPathGenerator(jit)
  71. , m_from(from)
  72. , m_to(jit->m_jit.label())
  73. {
  74. }
  75. protected:
  76. void linkFrom(SpeculativeJIT* jit)
  77. {
  78. m_from.link(&jit->m_jit);
  79. }
  80. void jumpTo(SpeculativeJIT* jit)
  81. {
  82. jit->m_jit.jump().linkTo(m_to, &jit->m_jit);
  83. }
  84. JumpType m_from;
  85. MacroAssembler::Label m_to;
  86. };
  87. template<typename JumpType, typename FunctionType, typename ResultType>
  88. class CallSlowPathGenerator : public JumpingSlowPathGenerator<JumpType> {
  89. public:
  90. CallSlowPathGenerator(
  91. JumpType from, SpeculativeJIT* jit, FunctionType function,
  92. SpillRegistersMode spillMode, ResultType result)
  93. : JumpingSlowPathGenerator<JumpType>(from, jit)
  94. , m_function(function)
  95. , m_spillMode(spillMode)
  96. , m_result(result)
  97. {
  98. if (m_spillMode == NeedToSpill)
  99. jit->silentSpillAllRegistersImpl(false, m_plans, result);
  100. }
  101. virtual MacroAssembler::Call call() const
  102. {
  103. return m_call;
  104. }
  105. protected:
  106. void setUp(SpeculativeJIT* jit)
  107. {
  108. this->linkFrom(jit);
  109. if (m_spillMode == NeedToSpill) {
  110. for (unsigned i = 0; i < m_plans.size(); ++i)
  111. jit->silentSpill(m_plans[i]);
  112. }
  113. }
  114. void recordCall(MacroAssembler::Call call)
  115. {
  116. m_call = call;
  117. }
  118. void tearDown(SpeculativeJIT* jit)
  119. {
  120. if (m_spillMode == NeedToSpill) {
  121. GPRReg canTrample = SpeculativeJIT::pickCanTrample(m_result);
  122. for (unsigned i = m_plans.size(); i--;)
  123. jit->silentFill(m_plans[i], canTrample);
  124. }
  125. this->jumpTo(jit);
  126. }
  127. FunctionType m_function;
  128. SpillRegistersMode m_spillMode;
  129. ResultType m_result;
  130. MacroAssembler::Call m_call;
  131. Vector<SilentRegisterSavePlan, 2> m_plans;
  132. };
  133. template<typename JumpType, typename FunctionType, typename ResultType>
  134. class CallResultAndNoArgumentsSlowPathGenerator
  135. : public CallSlowPathGenerator<JumpType, FunctionType, ResultType> {
  136. public:
  137. CallResultAndNoArgumentsSlowPathGenerator(
  138. JumpType from, SpeculativeJIT* jit, FunctionType function,
  139. SpillRegistersMode spillMode, ResultType result)
  140. : CallSlowPathGenerator<JumpType, FunctionType, ResultType>(
  141. from, jit, function, spillMode, result)
  142. {
  143. }
  144. protected:
  145. void generateInternal(SpeculativeJIT* jit)
  146. {
  147. this->setUp(jit);
  148. this->recordCall(jit->callOperation(this->m_function, this->m_result));
  149. this->tearDown(jit);
  150. }
  151. };
  152. template<
  153. typename JumpType, typename FunctionType, typename ResultType,
  154. typename ArgumentType1>
  155. class CallResultAndOneArgumentSlowPathGenerator
  156. : public CallSlowPathGenerator<JumpType, FunctionType, ResultType> {
  157. public:
  158. CallResultAndOneArgumentSlowPathGenerator(
  159. JumpType from, SpeculativeJIT* jit, FunctionType function,
  160. SpillRegistersMode spillMode, ResultType result, ArgumentType1 argument1)
  161. : CallSlowPathGenerator<JumpType, FunctionType, ResultType>(
  162. from, jit, function, spillMode, result)
  163. , m_argument1(argument1)
  164. {
  165. }
  166. protected:
  167. void generateInternal(SpeculativeJIT* jit)
  168. {
  169. this->setUp(jit);
  170. this->recordCall(jit->callOperation(this->m_function, this->m_result, m_argument1));
  171. this->tearDown(jit);
  172. }
  173. ArgumentType1 m_argument1;
  174. };
  175. template<
  176. typename JumpType, typename FunctionType, typename ResultType,
  177. typename ArgumentType1, typename ArgumentType2>
  178. class CallResultAndTwoArgumentsSlowPathGenerator
  179. : public CallSlowPathGenerator<JumpType, FunctionType, ResultType> {
  180. public:
  181. CallResultAndTwoArgumentsSlowPathGenerator(
  182. JumpType from, SpeculativeJIT* jit, FunctionType function,
  183. SpillRegistersMode spillMode, ResultType result, ArgumentType1 argument1,
  184. ArgumentType2 argument2)
  185. : CallSlowPathGenerator<JumpType, FunctionType, ResultType>(
  186. from, jit, function, spillMode, result)
  187. , m_argument1(argument1)
  188. , m_argument2(argument2)
  189. {
  190. }
  191. protected:
  192. void generateInternal(SpeculativeJIT* jit)
  193. {
  194. this->setUp(jit);
  195. this->recordCall(jit->callOperation(this->m_function, this->m_result, m_argument1, m_argument2));
  196. this->tearDown(jit);
  197. }
  198. ArgumentType1 m_argument1;
  199. ArgumentType2 m_argument2;
  200. };
  201. template<
  202. typename JumpType, typename FunctionType, typename ResultType,
  203. typename ArgumentType1, typename ArgumentType2, typename ArgumentType3>
  204. class CallResultAndThreeArgumentsSlowPathGenerator
  205. : public CallSlowPathGenerator<JumpType, FunctionType, ResultType> {
  206. public:
  207. CallResultAndThreeArgumentsSlowPathGenerator(
  208. JumpType from, SpeculativeJIT* jit, FunctionType function,
  209. SpillRegistersMode spillMode, ResultType result, ArgumentType1 argument1,
  210. ArgumentType2 argument2, ArgumentType3 argument3)
  211. : CallSlowPathGenerator<JumpType, FunctionType, ResultType>(
  212. from, jit, function, spillMode, result)
  213. , m_argument1(argument1)
  214. , m_argument2(argument2)
  215. , m_argument3(argument3)
  216. {
  217. }
  218. protected:
  219. void generateInternal(SpeculativeJIT* jit)
  220. {
  221. this->setUp(jit);
  222. this->recordCall(
  223. jit->callOperation(
  224. this->m_function, this->m_result, m_argument1, m_argument2,
  225. m_argument3));
  226. this->tearDown(jit);
  227. }
  228. ArgumentType1 m_argument1;
  229. ArgumentType2 m_argument2;
  230. ArgumentType3 m_argument3;
  231. };
  232. template<
  233. typename JumpType, typename FunctionType, typename ResultType,
  234. typename ArgumentType1, typename ArgumentType2, typename ArgumentType3,
  235. typename ArgumentType4>
  236. class CallResultAndFourArgumentsSlowPathGenerator
  237. : public CallSlowPathGenerator<JumpType, FunctionType, ResultType> {
  238. public:
  239. CallResultAndFourArgumentsSlowPathGenerator(
  240. JumpType from, SpeculativeJIT* jit, FunctionType function,
  241. SpillRegistersMode spillMode, ResultType result, ArgumentType1 argument1,
  242. ArgumentType2 argument2, ArgumentType3 argument3, ArgumentType4 argument4)
  243. : CallSlowPathGenerator<JumpType, FunctionType, ResultType>(
  244. from, jit, function, spillMode, result)
  245. , m_argument1(argument1)
  246. , m_argument2(argument2)
  247. , m_argument3(argument3)
  248. , m_argument4(argument4)
  249. {
  250. }
  251. protected:
  252. void generateInternal(SpeculativeJIT* jit)
  253. {
  254. this->setUp(jit);
  255. this->recordCall(
  256. jit->callOperation(
  257. this->m_function, this->m_result, m_argument1, m_argument2,
  258. m_argument3, m_argument4));
  259. this->tearDown(jit);
  260. }
  261. ArgumentType1 m_argument1;
  262. ArgumentType2 m_argument2;
  263. ArgumentType3 m_argument3;
  264. ArgumentType4 m_argument4;
  265. };
  266. template<
  267. typename JumpType, typename FunctionType, typename ResultType,
  268. typename ArgumentType1, typename ArgumentType2, typename ArgumentType3,
  269. typename ArgumentType4, typename ArgumentType5>
  270. class CallResultAndFiveArgumentsSlowPathGenerator
  271. : public CallSlowPathGenerator<JumpType, FunctionType, ResultType> {
  272. public:
  273. CallResultAndFiveArgumentsSlowPathGenerator(
  274. JumpType from, SpeculativeJIT* jit, FunctionType function,
  275. SpillRegistersMode spillMode, ResultType result, ArgumentType1 argument1,
  276. ArgumentType2 argument2, ArgumentType3 argument3, ArgumentType4 argument4,
  277. ArgumentType5 argument5)
  278. : CallSlowPathGenerator<JumpType, FunctionType, ResultType>(
  279. from, jit, function, spillMode, result)
  280. , m_argument1(argument1)
  281. , m_argument2(argument2)
  282. , m_argument3(argument3)
  283. , m_argument4(argument4)
  284. , m_argument5(argument5)
  285. {
  286. }
  287. protected:
  288. void generateInternal(SpeculativeJIT* jit)
  289. {
  290. this->setUp(jit);
  291. this->recordCall(
  292. jit->callOperation(
  293. this->m_function, this->m_result, m_argument1, m_argument2,
  294. m_argument3, m_argument4, m_argument5));
  295. this->tearDown(jit);
  296. }
  297. ArgumentType1 m_argument1;
  298. ArgumentType2 m_argument2;
  299. ArgumentType3 m_argument3;
  300. ArgumentType4 m_argument4;
  301. ArgumentType5 m_argument5;
  302. };
  303. template<typename JumpType, typename FunctionType, typename ResultType>
  304. inline PassOwnPtr<SlowPathGenerator> slowPathCall(
  305. JumpType from, SpeculativeJIT* jit, FunctionType function,
  306. ResultType result, SpillRegistersMode spillMode = NeedToSpill)
  307. {
  308. return adoptPtr(
  309. new CallResultAndNoArgumentsSlowPathGenerator<
  310. JumpType, FunctionType, ResultType>(
  311. from, jit, function, spillMode, result));
  312. }
  313. template<
  314. typename JumpType, typename FunctionType, typename ResultType,
  315. typename ArgumentType1>
  316. inline PassOwnPtr<SlowPathGenerator> slowPathCall(
  317. JumpType from, SpeculativeJIT* jit, FunctionType function,
  318. ResultType result, ArgumentType1 argument1,
  319. SpillRegistersMode spillMode = NeedToSpill)
  320. {
  321. return adoptPtr(
  322. new CallResultAndOneArgumentSlowPathGenerator<
  323. JumpType, FunctionType, ResultType, ArgumentType1>(
  324. from, jit, function, spillMode, result, argument1));
  325. }
  326. template<
  327. typename JumpType, typename FunctionType, typename ResultType,
  328. typename ArgumentType1, typename ArgumentType2>
  329. inline PassOwnPtr<SlowPathGenerator> slowPathCall(
  330. JumpType from, SpeculativeJIT* jit, FunctionType function,
  331. ResultType result, ArgumentType1 argument1, ArgumentType2 argument2,
  332. SpillRegistersMode spillMode = NeedToSpill)
  333. {
  334. return adoptPtr(
  335. new CallResultAndTwoArgumentsSlowPathGenerator<
  336. JumpType, FunctionType, ResultType, ArgumentType1, ArgumentType2>(
  337. from, jit, function, spillMode, result, argument1, argument2));
  338. }
  339. template<
  340. typename JumpType, typename FunctionType, typename ResultType,
  341. typename ArgumentType1, typename ArgumentType2, typename ArgumentType3>
  342. inline PassOwnPtr<SlowPathGenerator> slowPathCall(
  343. JumpType from, SpeculativeJIT* jit, FunctionType function,
  344. ResultType result, ArgumentType1 argument1, ArgumentType2 argument2,
  345. ArgumentType3 argument3, SpillRegistersMode spillMode = NeedToSpill)
  346. {
  347. return adoptPtr(
  348. new CallResultAndThreeArgumentsSlowPathGenerator<
  349. JumpType, FunctionType, ResultType, ArgumentType1, ArgumentType2,
  350. ArgumentType3>(
  351. from, jit, function, spillMode, result, argument1, argument2,
  352. argument3));
  353. }
  354. template<
  355. typename JumpType, typename FunctionType, typename ResultType,
  356. typename ArgumentType1, typename ArgumentType2, typename ArgumentType3,
  357. typename ArgumentType4>
  358. inline PassOwnPtr<SlowPathGenerator> slowPathCall(
  359. JumpType from, SpeculativeJIT* jit, FunctionType function,
  360. ResultType result, ArgumentType1 argument1, ArgumentType2 argument2,
  361. ArgumentType3 argument3, ArgumentType4 argument4,
  362. SpillRegistersMode spillMode = NeedToSpill)
  363. {
  364. return adoptPtr(
  365. new CallResultAndFourArgumentsSlowPathGenerator<
  366. JumpType, FunctionType, ResultType, ArgumentType1, ArgumentType2,
  367. ArgumentType3, ArgumentType4>(
  368. from, jit, function, spillMode, result, argument1, argument2,
  369. argument3, argument4));
  370. }
  371. template<
  372. typename JumpType, typename FunctionType, typename ResultType,
  373. typename ArgumentType1, typename ArgumentType2, typename ArgumentType3,
  374. typename ArgumentType4, typename ArgumentType5>
  375. inline PassOwnPtr<SlowPathGenerator> slowPathCall(
  376. JumpType from, SpeculativeJIT* jit, FunctionType function,
  377. ResultType result, ArgumentType1 argument1, ArgumentType2 argument2,
  378. ArgumentType3 argument3, ArgumentType4 argument4, ArgumentType5 argument5,
  379. SpillRegistersMode spillMode = NeedToSpill)
  380. {
  381. return adoptPtr(
  382. new CallResultAndFiveArgumentsSlowPathGenerator<
  383. JumpType, FunctionType, ResultType, ArgumentType1, ArgumentType2,
  384. ArgumentType3, ArgumentType4, ArgumentType5>(
  385. from, jit, function, spillMode, result, argument1, argument2,
  386. argument3, argument4, argument5));
  387. }
  388. template<typename JumpType, typename DestinationType, typename SourceType, unsigned numberOfAssignments>
  389. class AssigningSlowPathGenerator : public JumpingSlowPathGenerator<JumpType> {
  390. public:
  391. AssigningSlowPathGenerator(
  392. JumpType from, SpeculativeJIT* jit,
  393. DestinationType destination[numberOfAssignments],
  394. SourceType source[numberOfAssignments])
  395. : JumpingSlowPathGenerator<JumpType>(from, jit)
  396. {
  397. for (unsigned i = numberOfAssignments; i--;) {
  398. m_destination[i] = destination[i];
  399. m_source[i] = source[i];
  400. }
  401. }
  402. protected:
  403. virtual void generateInternal(SpeculativeJIT* jit)
  404. {
  405. this->linkFrom(jit);
  406. for (unsigned i = numberOfAssignments; i--;)
  407. jit->m_jit.move(m_source[i], m_destination[i]);
  408. this->jumpTo(jit);
  409. }
  410. private:
  411. DestinationType m_destination[numberOfAssignments];
  412. SourceType m_source[numberOfAssignments];
  413. };
  414. template<typename JumpType, typename DestinationType, typename SourceType, unsigned numberOfAssignments>
  415. inline PassOwnPtr<SlowPathGenerator> slowPathMove(
  416. JumpType from, SpeculativeJIT* jit, SourceType source[numberOfAssignments], DestinationType destination[numberOfAssignments])
  417. {
  418. return adoptPtr(
  419. new AssigningSlowPathGenerator<
  420. JumpType, DestinationType, SourceType, numberOfAssignments>(
  421. from, jit, destination, source));
  422. }
  423. template<typename JumpType, typename DestinationType, typename SourceType>
  424. inline PassOwnPtr<SlowPathGenerator> slowPathMove(
  425. JumpType from, SpeculativeJIT* jit, SourceType source, DestinationType destination)
  426. {
  427. SourceType sourceArray[1] = { source };
  428. DestinationType destinationArray[1] = { destination };
  429. return adoptPtr(
  430. new AssigningSlowPathGenerator<
  431. JumpType, DestinationType, SourceType, 1>(
  432. from, jit, destinationArray, sourceArray));
  433. }
  434. template<typename JumpType, typename DestinationType, typename SourceType>
  435. inline PassOwnPtr<SlowPathGenerator> slowPathMove(
  436. JumpType from, SpeculativeJIT* jit, SourceType source1, DestinationType destination1, SourceType source2, DestinationType destination2)
  437. {
  438. SourceType sourceArray[2] = { source1, source2 };
  439. DestinationType destinationArray[2] = { destination1, destination2 };
  440. return adoptPtr(
  441. new AssigningSlowPathGenerator<
  442. JumpType, DestinationType, SourceType, 2>(
  443. from, jit, destinationArray, sourceArray));
  444. }
  445. } } // namespace JSC::DFG
  446. #endif // ENABLD(DFG_JIT)
  447. #endif // DFGSlowPathGenerator_h