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