[JSC] useJIT should subsume useRegExpJIT
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGCapabilities.cpp
1 /*
2  * Copyright (C) 2011-2017 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
26 #include "config.h"
27 #include "DFGCapabilities.h"
28
29 #if ENABLE(DFG_JIT)
30
31 #include "CodeBlock.h"
32 #include "DFGCommon.h"
33 #include "InterpreterInlines.h"
34 #include "JSCInlines.h"
35 #include "Options.h"
36
37 namespace JSC { namespace DFG {
38
39 bool isSupported()
40 {
41     return VM::canUseJIT() && Options::useDFGJIT() && MacroAssembler::supportsFloatingPoint();
42 }
43
44 bool isSupportedForInlining(CodeBlock* codeBlock)
45 {
46     return codeBlock->ownerExecutable()->isInliningCandidate();
47 }
48
49 bool mightCompileEval(CodeBlock* codeBlock)
50 {
51     return isSupported()
52         && codeBlock->instructionCount() <= Options::maximumOptimizationCandidateInstructionCount()
53         && codeBlock->ownerExecutable()->isOkToOptimize();
54 }
55 bool mightCompileProgram(CodeBlock* codeBlock)
56 {
57     return isSupported()
58         && codeBlock->instructionCount() <= Options::maximumOptimizationCandidateInstructionCount()
59         && codeBlock->ownerExecutable()->isOkToOptimize();
60 }
61 bool mightCompileFunctionForCall(CodeBlock* codeBlock)
62 {
63     return isSupported()
64         && codeBlock->instructionCount() <= Options::maximumOptimizationCandidateInstructionCount()
65         && codeBlock->ownerExecutable()->isOkToOptimize();
66 }
67 bool mightCompileFunctionForConstruct(CodeBlock* codeBlock)
68 {
69     return isSupported()
70         && codeBlock->instructionCount() <= Options::maximumOptimizationCandidateInstructionCount()
71         && codeBlock->ownerExecutable()->isOkToOptimize();
72 }
73
74 bool mightInlineFunctionForCall(CodeBlock* codeBlock)
75 {
76     return codeBlock->instructionCount() <= Options::maximumFunctionForCallInlineCandidateInstructionCount()
77         && isSupportedForInlining(codeBlock);
78 }
79 bool mightInlineFunctionForClosureCall(CodeBlock* codeBlock)
80 {
81     return codeBlock->instructionCount() <= Options::maximumFunctionForClosureCallInlineCandidateInstructionCount()
82         && isSupportedForInlining(codeBlock);
83 }
84 bool mightInlineFunctionForConstruct(CodeBlock* codeBlock)
85 {
86     return codeBlock->instructionCount() <= Options::maximumFunctionForConstructInlineCandidateInstructionCount()
87         && isSupportedForInlining(codeBlock);
88 }
89 bool canUseOSRExitFuzzing(CodeBlock* codeBlock)
90 {
91     return codeBlock->ownerExecutable()->canUseOSRExitFuzzing();
92 }
93
94 static bool verboseCapabilities()
95 {
96     return verboseCompilationEnabled() || Options::verboseDFGFailure();
97 }
98
99 inline void debugFail(CodeBlock* codeBlock, OpcodeID opcodeID, CapabilityLevel result)
100 {
101     if (verboseCapabilities() && !canCompile(result))
102         dataLog("DFG rejecting opcode in ", *codeBlock, " because of opcode ", opcodeNames[opcodeID], "\n");
103 }
104
105 CapabilityLevel capabilityLevel(OpcodeID opcodeID, CodeBlock* codeBlock, const Instruction* pc)
106 {
107     UNUSED_PARAM(codeBlock); // This function does some bytecode parsing. Ordinarily bytecode parsing requires the owning CodeBlock. It's sort of strange that we don't use it here right now.
108     UNUSED_PARAM(pc);
109     
110     switch (opcodeID) {
111     case op_wide:
112         RELEASE_ASSERT_NOT_REACHED();
113     case op_enter:
114     case op_to_this:
115     case op_argument_count:
116     case op_check_tdz:
117     case op_create_this:
118     case op_bitnot:
119     case op_bitand:
120     case op_bitor:
121     case op_bitxor:
122     case op_rshift:
123     case op_lshift:
124     case op_urshift:
125     case op_unsigned:
126     case op_inc:
127     case op_dec:
128     case op_add:
129     case op_sub:
130     case op_negate:
131     case op_mul:
132     case op_mod:
133     case op_pow:
134     case op_div:
135     case op_debug:
136     case op_profile_type:
137     case op_profile_control_flow:
138     case op_mov:
139     case op_overrides_has_instance:
140     case op_identity_with_profile:
141     case op_instanceof:
142     case op_instanceof_custom:
143     case op_is_empty:
144     case op_is_undefined:
145     case op_is_undefined_or_null:
146     case op_is_boolean:
147     case op_is_number:
148     case op_is_object:
149     case op_is_object_or_null:
150     case op_is_cell_with_type:
151     case op_is_function:
152     case op_not:
153     case op_less:
154     case op_lesseq:
155     case op_greater:
156     case op_greatereq:
157     case op_below:
158     case op_beloweq:
159     case op_eq:
160     case op_eq_null:
161     case op_stricteq:
162     case op_neq:
163     case op_neq_null:
164     case op_nstricteq:
165     case op_get_by_val:
166     case op_put_by_val:
167     case op_put_by_val_direct:
168     case op_try_get_by_id:
169     case op_get_by_id:
170     case op_get_by_id_with_this:
171     case op_get_by_id_direct:
172     case op_get_by_val_with_this:
173     case op_put_by_id:
174     case op_put_by_id_with_this:
175     case op_put_by_val_with_this:
176     case op_put_getter_by_id:
177     case op_put_setter_by_id:
178     case op_put_getter_setter_by_id:
179     case op_put_getter_by_val:
180     case op_put_setter_by_val:
181     case op_define_data_property:
182     case op_define_accessor_property:
183     case op_del_by_id:
184     case op_del_by_val:
185     case op_jmp:
186     case op_jtrue:
187     case op_jfalse:
188     case op_jeq_null:
189     case op_jneq_null:
190     case op_jless:
191     case op_jlesseq:
192     case op_jgreater:
193     case op_jgreatereq:
194     case op_jnless:
195     case op_jnlesseq:
196     case op_jngreater:
197     case op_jngreatereq:
198     case op_jeq:
199     case op_jneq:
200     case op_jstricteq:
201     case op_jnstricteq:
202     case op_jbelow:
203     case op_jbeloweq:
204     case op_loop_hint:
205     case op_check_traps:
206     case op_nop:
207     case op_ret:
208     case op_end:
209     case op_new_object:
210     case op_new_array:
211     case op_new_array_with_size:
212     case op_new_array_buffer:
213     case op_new_array_with_spread:
214     case op_spread:
215     case op_strcat:
216     case op_to_primitive:
217     case op_throw:
218     case op_throw_static_error:
219     case op_call:
220     case op_tail_call:
221     case op_construct:
222     case op_call_varargs:
223     case op_tail_call_varargs:
224     case op_tail_call_forward_arguments:
225     case op_construct_varargs:
226     case op_create_direct_arguments:
227     case op_create_scoped_arguments:
228     case op_create_cloned_arguments:
229     case op_get_from_arguments:
230     case op_put_to_arguments:
231     case op_get_argument:
232     case op_jneq_ptr:
233     case op_typeof:
234     case op_to_number:
235     case op_to_string:
236     case op_to_object:
237     case op_switch_imm:
238     case op_switch_char:
239     case op_in_by_val:
240     case op_in_by_id:
241     case op_get_scope:
242     case op_get_from_scope:
243     case op_get_enumerable_length:
244     case op_has_generic_property:
245     case op_has_structure_property:
246     case op_has_indexed_property:
247     case op_get_direct_pname:
248     case op_get_property_enumerator:
249     case op_enumerator_structure_pname:
250     case op_enumerator_generic_pname:
251     case op_to_index_string:
252     case op_new_func:
253     case op_new_func_exp:
254     case op_new_generator_func:
255     case op_new_generator_func_exp:
256     case op_new_async_generator_func:
257     case op_new_async_generator_func_exp:
258     case op_new_async_func:
259     case op_new_async_func_exp:
260     case op_set_function_name:
261     case op_create_lexical_environment:
262     case op_push_with_scope:
263     case op_get_parent_scope:
264     case op_catch:
265     case op_create_rest:
266     case op_get_rest_length:
267     case op_log_shadow_chicken_prologue:
268     case op_log_shadow_chicken_tail:
269     case op_put_to_scope:
270     case op_resolve_scope:
271     case op_resolve_scope_for_hoisting_func_decl_in_eval:
272     case op_new_regexp:
273     case op_unreachable:
274     case op_super_sampler_begin:
275     case op_super_sampler_end:
276         return CanCompileAndInline;
277
278     case op_switch_string: // Don't inline because we don't want to copy string tables in the concurrent JIT.
279     case op_call_eval:
280         return CanCompile;
281
282     case op_yield:
283     case op_create_generator_frame_environment:
284     case llint_program_prologue:
285     case llint_eval_prologue:
286     case llint_module_program_prologue:
287     case llint_function_for_call_prologue:
288     case llint_function_for_construct_prologue:
289     case llint_function_for_call_arity_check:
290     case llint_function_for_construct_arity_check:
291     case llint_generic_return_point:
292     case llint_throw_from_slow_path_trampoline:
293     case llint_throw_during_call_trampoline:
294     case llint_native_call_trampoline:
295     case llint_native_construct_trampoline:
296     case llint_internal_function_call_trampoline:
297     case llint_internal_function_construct_trampoline:
298     case handleUncaughtException:
299         return CannotCompile;
300     }
301     return CannotCompile;
302 }
303
304 CapabilityLevel capabilityLevel(CodeBlock* codeBlock)
305 {
306     CapabilityLevel result = CanCompileAndInline;
307     
308     for (const auto& instruction : codeBlock->instructions()) {
309         switch (instruction->opcodeID()) {
310 #define DEFINE_OP(opcode, length) \
311         case opcode: { \
312             CapabilityLevel newResult = leastUpperBound(result, capabilityLevel(opcode, codeBlock, instruction.ptr())); \
313             if (newResult != result) { \
314                 debugFail(codeBlock, opcode, newResult); \
315                 result = newResult; \
316             } \
317             break; \
318         }
319             FOR_EACH_OPCODE_ID(DEFINE_OP)
320 #undef DEFINE_OP
321         default:
322             RELEASE_ASSERT_NOT_REACHED();
323             break;
324         }
325     }
326     
327     return result;
328 }
329
330 } } // namespace JSC::DFG
331
332 #endif