DFGCapabilities.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. /*
  2. * Copyright (C) 2011, 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 DFGCapabilities_h
  26. #define DFGCapabilities_h
  27. #include "Intrinsic.h"
  28. #include "DFGCommon.h"
  29. #include "DFGNode.h"
  30. #include "Executable.h"
  31. #include "Options.h"
  32. #include "Interpreter.h"
  33. #include <wtf/Platform.h>
  34. namespace JSC { namespace DFG {
  35. #if ENABLE(DFG_JIT)
  36. // Fast check functions; if they return true it is still necessary to
  37. // check opcodes.
  38. bool mightCompileEval(CodeBlock*);
  39. bool mightCompileProgram(CodeBlock*);
  40. bool mightCompileFunctionForCall(CodeBlock*);
  41. bool mightCompileFunctionForConstruct(CodeBlock*);
  42. bool mightInlineFunctionForCall(CodeBlock*);
  43. bool mightInlineFunctionForClosureCall(CodeBlock*);
  44. bool mightInlineFunctionForConstruct(CodeBlock*);
  45. // Opcode checking.
  46. inline bool canInlineResolveOperations(ResolveOperations* operations)
  47. {
  48. for (unsigned i = 0; i < operations->size(); i++) {
  49. switch (operations->data()[i].m_operation) {
  50. case ResolveOperation::ReturnGlobalObjectAsBase:
  51. case ResolveOperation::SetBaseToGlobal:
  52. case ResolveOperation::SetBaseToUndefined:
  53. case ResolveOperation::GetAndReturnGlobalProperty:
  54. case ResolveOperation::GetAndReturnGlobalVar:
  55. case ResolveOperation::GetAndReturnGlobalVarWatchable:
  56. case ResolveOperation::SkipScopes:
  57. case ResolveOperation::SetBaseToScope:
  58. case ResolveOperation::ReturnScopeAsBase:
  59. case ResolveOperation::GetAndReturnScopedVar:
  60. continue;
  61. case ResolveOperation::Fail:
  62. // Fall-back resolves don't know how to deal with the ExecState* having a different
  63. // global object (and scope) than the inlined code that is invoking that resolve.
  64. return false;
  65. case ResolveOperation::SkipTopScopeNode:
  66. // We don't inline code blocks that create activations. Creation of
  67. // activations is the only thing that leads to SkipTopScopeNode.
  68. return false;
  69. case ResolveOperation::CheckForDynamicEntriesBeforeGlobalScope:
  70. // This would be easy to support in all cases.
  71. return false;
  72. }
  73. }
  74. return true;
  75. }
  76. inline CapabilityLevel canCompileOpcode(OpcodeID opcodeID, CodeBlock*, Instruction*)
  77. {
  78. switch (opcodeID) {
  79. case op_enter:
  80. case op_convert_this:
  81. case op_create_this:
  82. case op_get_callee:
  83. case op_bitand:
  84. case op_bitor:
  85. case op_bitxor:
  86. case op_rshift:
  87. case op_lshift:
  88. case op_urshift:
  89. case op_inc:
  90. case op_dec:
  91. case op_add:
  92. case op_sub:
  93. case op_negate:
  94. case op_mul:
  95. case op_mod:
  96. case op_div:
  97. #if ENABLE(DEBUG_WITH_BREAKPOINT)
  98. case op_debug:
  99. #endif
  100. case op_mov:
  101. case op_check_has_instance:
  102. case op_instanceof:
  103. case op_is_undefined:
  104. case op_is_boolean:
  105. case op_is_number:
  106. case op_is_string:
  107. case op_is_object:
  108. case op_is_function:
  109. case op_not:
  110. case op_less:
  111. case op_lesseq:
  112. case op_greater:
  113. case op_greatereq:
  114. case op_eq:
  115. case op_eq_null:
  116. case op_stricteq:
  117. case op_neq:
  118. case op_neq_null:
  119. case op_nstricteq:
  120. case op_get_by_val:
  121. case op_put_by_val:
  122. case op_get_by_id:
  123. case op_get_by_id_out_of_line:
  124. case op_get_array_length:
  125. case op_put_by_id:
  126. case op_put_by_id_out_of_line:
  127. case op_put_by_id_transition_direct:
  128. case op_put_by_id_transition_direct_out_of_line:
  129. case op_put_by_id_transition_normal:
  130. case op_put_by_id_transition_normal_out_of_line:
  131. case op_init_global_const_nop:
  132. case op_init_global_const:
  133. case op_init_global_const_check:
  134. case op_jmp:
  135. case op_jtrue:
  136. case op_jfalse:
  137. case op_jeq_null:
  138. case op_jneq_null:
  139. case op_jless:
  140. case op_jlesseq:
  141. case op_jgreater:
  142. case op_jgreatereq:
  143. case op_jnless:
  144. case op_jnlesseq:
  145. case op_jngreater:
  146. case op_jngreatereq:
  147. case op_loop_hint:
  148. case op_ret:
  149. case op_end:
  150. case op_call_put_result:
  151. case op_new_object:
  152. case op_new_array:
  153. case op_new_array_with_size:
  154. case op_new_array_buffer:
  155. case op_strcat:
  156. case op_to_primitive:
  157. case op_throw:
  158. case op_throw_static_error:
  159. case op_call:
  160. case op_construct:
  161. case op_new_regexp:
  162. case op_init_lazy_reg:
  163. case op_create_activation:
  164. case op_tear_off_activation:
  165. case op_create_arguments:
  166. case op_tear_off_arguments:
  167. case op_new_func:
  168. case op_new_func_exp:
  169. case op_get_argument_by_val:
  170. case op_get_arguments_length:
  171. case op_jneq_ptr:
  172. case op_put_to_base_variable:
  173. case op_put_to_base:
  174. case op_typeof:
  175. case op_to_number:
  176. return CanCompile;
  177. case op_call_varargs:
  178. return MayInline;
  179. case op_resolve:
  180. case op_resolve_global_property:
  181. case op_resolve_global_var:
  182. case op_resolve_scoped_var:
  183. case op_resolve_scoped_var_on_top_scope:
  184. case op_resolve_scoped_var_with_top_scope_check:
  185. return CanCompile;
  186. case op_get_scoped_var:
  187. case op_put_scoped_var:
  188. return CanCompile;
  189. case op_resolve_base_to_global:
  190. case op_resolve_base_to_global_dynamic:
  191. case op_resolve_base_to_scope:
  192. case op_resolve_base_to_scope_with_top_scope_check:
  193. case op_resolve_base:
  194. case op_resolve_with_base:
  195. case op_resolve_with_this:
  196. return CanCompile;
  197. default:
  198. return CannotCompile;
  199. }
  200. }
  201. inline bool canInlineOpcode(OpcodeID opcodeID, CodeBlock* codeBlock, Instruction* pc)
  202. {
  203. switch (opcodeID) {
  204. case op_resolve:
  205. case op_resolve_global_property:
  206. case op_resolve_global_var:
  207. case op_resolve_scoped_var:
  208. case op_resolve_scoped_var_on_top_scope:
  209. case op_resolve_scoped_var_with_top_scope_check:
  210. return canInlineResolveOperations(pc[3].u.resolveOperations);
  211. case op_resolve_base_to_global:
  212. case op_resolve_base_to_global_dynamic:
  213. case op_resolve_base_to_scope:
  214. case op_resolve_base_to_scope_with_top_scope_check:
  215. case op_resolve_base:
  216. case op_resolve_with_base:
  217. case op_resolve_with_this:
  218. return canInlineResolveOperations(pc[4].u.resolveOperations);
  219. case op_get_scoped_var:
  220. case op_put_scoped_var:
  221. return !codeBlock->needsFullScopeChain();
  222. // Inlining doesn't correctly remap regular expression operands.
  223. case op_new_regexp:
  224. // We don't support inlining code that creates activations or has nested functions.
  225. case op_create_activation:
  226. case op_tear_off_activation:
  227. case op_new_func:
  228. case op_new_func_exp:
  229. return false;
  230. // Inlining supports op_call_varargs if it's a call that just forwards the caller's
  231. // arguments.
  232. case op_call_varargs:
  233. return codeBlock->usesArguments() && pc[3].u.operand == codeBlock->argumentsRegister();
  234. default:
  235. return canCompileOpcode(opcodeID, codeBlock, pc) == CanCompile;
  236. }
  237. }
  238. CapabilityLevel canCompileOpcodes(CodeBlock*);
  239. bool canInlineOpcodes(CodeBlock*);
  240. #else // ENABLE(DFG_JIT)
  241. inline bool mightCompileEval(CodeBlock*) { return false; }
  242. inline bool mightCompileProgram(CodeBlock*) { return false; }
  243. inline bool mightCompileFunctionForCall(CodeBlock*) { return false; }
  244. inline bool mightCompileFunctionForConstruct(CodeBlock*) { return false; }
  245. inline bool mightInlineFunctionForCall(CodeBlock*) { return false; }
  246. inline bool mightInlineFunctionForClosureCall(CodeBlock*) { return false; }
  247. inline bool mightInlineFunctionForConstruct(CodeBlock*) { return false; }
  248. inline CapabilityLevel canCompileOpcode(OpcodeID, CodeBlock*, Instruction*) { return CannotCompile; }
  249. inline bool canInlineOpcode(OpcodeID, CodeBlock*, Instruction*) { return false; }
  250. inline CapabilityLevel canCompileOpcodes(CodeBlock*) { return CannotCompile; }
  251. inline bool canInlineOpcodes(CodeBlock*) { return false; }
  252. #endif // ENABLE(DFG_JIT)
  253. inline CapabilityLevel canCompileEval(CodeBlock* codeBlock)
  254. {
  255. if (!mightCompileEval(codeBlock))
  256. return CannotCompile;
  257. return canCompileOpcodes(codeBlock);
  258. }
  259. inline CapabilityLevel canCompileProgram(CodeBlock* codeBlock)
  260. {
  261. if (!mightCompileProgram(codeBlock))
  262. return CannotCompile;
  263. return canCompileOpcodes(codeBlock);
  264. }
  265. inline CapabilityLevel canCompileFunctionForCall(CodeBlock* codeBlock)
  266. {
  267. if (!mightCompileFunctionForCall(codeBlock))
  268. return CannotCompile;
  269. return canCompileOpcodes(codeBlock);
  270. }
  271. inline CapabilityLevel canCompileFunctionForConstruct(CodeBlock* codeBlock)
  272. {
  273. if (!mightCompileFunctionForConstruct(codeBlock))
  274. return CannotCompile;
  275. return canCompileOpcodes(codeBlock);
  276. }
  277. inline bool canInlineFunctionForCall(CodeBlock* codeBlock)
  278. {
  279. return mightInlineFunctionForCall(codeBlock) && canInlineOpcodes(codeBlock);
  280. }
  281. inline bool canInlineFunctionForClosureCall(CodeBlock* codeBlock)
  282. {
  283. return mightInlineFunctionForClosureCall(codeBlock) && canInlineOpcodes(codeBlock);
  284. }
  285. inline bool canInlineFunctionForConstruct(CodeBlock* codeBlock)
  286. {
  287. return mightInlineFunctionForConstruct(codeBlock) && canInlineOpcodes(codeBlock);
  288. }
  289. inline bool mightInlineFunctionFor(CodeBlock* codeBlock, CodeSpecializationKind kind)
  290. {
  291. if (kind == CodeForCall)
  292. return mightInlineFunctionForCall(codeBlock);
  293. ASSERT(kind == CodeForConstruct);
  294. return mightInlineFunctionForConstruct(codeBlock);
  295. }
  296. inline bool canInlineFunctionFor(CodeBlock* codeBlock, CodeSpecializationKind kind, bool isClosureCall)
  297. {
  298. if (isClosureCall) {
  299. ASSERT(kind == CodeForCall);
  300. return canInlineFunctionForClosureCall(codeBlock);
  301. }
  302. if (kind == CodeForCall)
  303. return canInlineFunctionForCall(codeBlock);
  304. ASSERT(kind == CodeForConstruct);
  305. return canInlineFunctionForConstruct(codeBlock);
  306. }
  307. } } // namespace JSC::DFG
  308. #endif // DFGCapabilities_h