a89c697f6cbab8ce40bbbe63e1bbc95c83beb13c
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGCapabilities.h
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
26 #ifndef DFGCapabilities_h
27 #define DFGCapabilities_h
28
29 #include "Intrinsic.h"
30 #include "DFGCommon.h"
31 #include "DFGNode.h"
32 #include "Executable.h"
33 #include "Options.h"
34 #include "Interpreter.h"
35 #include <wtf/Platform.h>
36
37 namespace JSC { namespace DFG {
38
39 #if ENABLE(DFG_JIT)
40 // Fast check functions; if they return true it is still necessary to
41 // check opcodes.
42 inline bool mightCompileEval(CodeBlock* codeBlock)
43 {
44     return codeBlock->instructionCount() <= Options::maximumOptimizationCandidateInstructionCount();
45 }
46 inline bool mightCompileProgram(CodeBlock* codeBlock)
47 {
48     return codeBlock->instructionCount() <= Options::maximumOptimizationCandidateInstructionCount();
49 }
50 inline bool mightCompileFunctionForCall(CodeBlock* codeBlock)
51 {
52     return codeBlock->instructionCount() <= Options::maximumOptimizationCandidateInstructionCount();
53 }
54 inline bool mightCompileFunctionForConstruct(CodeBlock* codeBlock)
55 {
56     return codeBlock->instructionCount() <= Options::maximumOptimizationCandidateInstructionCount();
57 }
58
59 inline bool mightInlineFunctionForCall(CodeBlock* codeBlock)
60 {
61     return codeBlock->instructionCount() <= Options::maximumFunctionForCallInlineCandidateInstructionCount()
62         && !codeBlock->ownerExecutable()->needsActivation();
63 }
64 inline bool mightInlineFunctionForConstruct(CodeBlock* codeBlock)
65 {
66     return codeBlock->instructionCount() <= Options::maximumFunctionForConstructInlineCandidateInstructionCount()
67         && !codeBlock->ownerExecutable()->needsActivation();
68 }
69
70 // Opcode checking.
71 inline bool canInlineResolveOperations(OpcodeID opcode, ResolveOperations* operations)
72 {
73     // Don't try to inline a resolve for which we have no information
74     if (operations->isEmpty())
75         return false;
76
77     for (unsigned i = 0; i < operations->size(); i++) {
78         switch (operations->data()[i].m_operation) {
79         case ResolveOperation::ReturnGlobalObjectAsBase:
80         case ResolveOperation::SetBaseToGlobal:
81         case ResolveOperation::SetBaseToUndefined:
82         case ResolveOperation::GetAndReturnGlobalProperty:
83         case ResolveOperation::GetAndReturnGlobalVar:
84         case ResolveOperation::GetAndReturnGlobalVarWatchable:
85             continue;
86
87         case ResolveOperation::Fail:
88             // The DFG can handle generic cases of failed resolves
89             ASSERT(opcode != op_resolve_base_to_global_dynamic);
90             ASSERT(opcode != op_resolve_base_to_scope_with_top_scope_check);
91             ASSERT(opcode != op_resolve_base_to_global);
92             ASSERT(opcode != op_resolve_base_to_scope);
93             if (opcode != op_resolve && opcode != op_resolve_base)
94                 return false;
95
96         case ResolveOperation::SkipTopScopeNode:
97         case ResolveOperation::SkipScopes:
98         case ResolveOperation::SetBaseToScope:
99         case ResolveOperation::ReturnScopeAsBase:
100         case ResolveOperation::GetAndReturnScopedVar:
101             // These opcodes would be easy to support with inlining, but we currently don't do it.
102             // The issue is that the scope chain will not be set correctly.
103             return false;
104
105         case ResolveOperation::CheckForDynamicEntriesBeforeGlobalScope:
106             // This would be easy to support in all cases.
107             return false;
108         }
109     }
110     return true;
111 }
112
113 inline CapabilityLevel canCompileOpcode(OpcodeID opcodeID, CodeBlock*, Instruction*)
114 {
115     switch (opcodeID) {
116     case op_enter:
117     case op_convert_this:
118     case op_create_this:
119     case op_get_callee:
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_pre_inc:
127     case op_post_inc:
128     case op_pre_dec:
129     case op_post_dec:
130     case op_add:
131     case op_sub:
132     case op_negate:
133     case op_mul:
134     case op_mod:
135     case op_div:
136 #if ENABLE(DEBUG_WITH_BREAKPOINT)
137     case op_debug:
138 #endif
139     case op_mov:
140     case op_check_has_instance:
141     case op_instanceof:
142     case op_is_undefined:
143     case op_is_boolean:
144     case op_is_number:
145     case op_is_string:
146     case op_is_object:
147     case op_is_function:
148     case op_not:
149     case op_less:
150     case op_lesseq:
151     case op_greater:
152     case op_greatereq:
153     case op_eq:
154     case op_eq_null:
155     case op_stricteq:
156     case op_neq:
157     case op_neq_null:
158     case op_nstricteq:
159     case op_get_by_val:
160     case op_put_by_val:
161     case op_get_by_id:
162     case op_get_by_id_out_of_line:
163     case op_get_array_length:
164     case op_put_by_id:
165     case op_put_by_id_out_of_line:
166     case op_put_by_id_transition_direct:
167     case op_put_by_id_transition_direct_out_of_line:
168     case op_put_by_id_transition_normal:
169     case op_put_by_id_transition_normal_out_of_line:
170     case op_init_global_const_nop:
171     case op_init_global_const:
172     case op_init_global_const_check:
173     case op_jmp:
174     case op_loop:
175     case op_jtrue:
176     case op_jfalse:
177     case op_loop_if_true:
178     case op_loop_if_false:
179     case op_jeq_null:
180     case op_jneq_null:
181     case op_jless:
182     case op_jlesseq:
183     case op_jgreater:
184     case op_jgreatereq:
185     case op_jnless:
186     case op_jnlesseq:
187     case op_jngreater:
188     case op_jngreatereq:
189     case op_loop_hint:
190     case op_loop_if_less:
191     case op_loop_if_lesseq:
192     case op_loop_if_greater:
193     case op_loop_if_greatereq:
194     case op_ret:
195     case op_end:
196     case op_call_put_result:
197     case op_new_object:
198     case op_new_array:
199     case op_new_array_with_size:
200     case op_new_array_buffer:
201     case op_strcat:
202     case op_to_primitive:
203     case op_throw:
204     case op_throw_static_error:
205     case op_call:
206     case op_construct:
207     case op_new_regexp: 
208     case op_init_lazy_reg:
209     case op_create_activation:
210     case op_tear_off_activation:
211     case op_create_arguments:
212     case op_tear_off_arguments:
213     case op_new_func:
214     case op_new_func_exp:
215     case op_get_argument_by_val:
216     case op_get_arguments_length:
217     case op_jneq_ptr:
218     case op_put_to_base_variable:
219     case op_put_to_base:
220         return CanCompile;
221         
222     case op_call_varargs:
223         return ShouldProfile;
224
225     case op_resolve:
226     case op_resolve_global_property:
227     case op_resolve_global_var:
228     case op_resolve_scoped_var:
229     case op_resolve_scoped_var_on_top_scope:
230     case op_resolve_scoped_var_with_top_scope_check:
231         return CanCompile;
232
233     case op_resolve_base_to_global:
234     case op_resolve_base_to_global_dynamic:
235     case op_resolve_base_to_scope:
236     case op_resolve_base_to_scope_with_top_scope_check:
237     case op_resolve_base:
238     case op_resolve_with_base:
239     case op_resolve_with_this:
240         return CanCompile;
241
242     default:
243         return CannotCompile;
244     }
245 }
246
247 inline bool canInlineOpcode(OpcodeID opcodeID, CodeBlock* codeBlock, Instruction* pc)
248 {
249     switch (opcodeID) {
250     case op_resolve:
251     case op_resolve_global_property:
252     case op_resolve_global_var:
253     case op_resolve_scoped_var:
254     case op_resolve_scoped_var_on_top_scope:
255     case op_resolve_scoped_var_with_top_scope_check:
256         return canInlineResolveOperations(opcodeID, codeBlock->resolveOperations(pc[3].u.operand));
257
258     case op_resolve_base_to_global:
259     case op_resolve_base_to_global_dynamic:
260     case op_resolve_base_to_scope:
261     case op_resolve_base_to_scope_with_top_scope_check:
262     case op_resolve_base:
263     case op_resolve_with_base:
264     case op_resolve_with_this:
265         return canInlineResolveOperations(opcodeID, codeBlock->resolveOperations(pc[4].u.operand));
266         
267     // Inlining doesn't correctly remap regular expression operands.
268     case op_new_regexp:
269         
270     // We don't support inlining code that creates activations or has nested functions.
271     case op_create_activation:
272     case op_tear_off_activation:
273     case op_new_func:
274     case op_new_func_exp:
275         return false;
276         
277     // Inlining supports op_call_varargs if it's a call that just forwards the caller's
278     // arguments.
279     case op_call_varargs:
280         return codeBlock->usesArguments() && pc[3].u.operand == codeBlock->argumentsRegister();
281         
282     default:
283         return canCompileOpcode(opcodeID, codeBlock, pc) == CanCompile;
284     }
285 }
286
287 CapabilityLevel canCompileOpcodes(CodeBlock*);
288 bool canInlineOpcodes(CodeBlock*);
289 #else // ENABLE(DFG_JIT)
290 inline bool mightCompileEval(CodeBlock*) { return false; }
291 inline bool mightCompileProgram(CodeBlock*) { return false; }
292 inline bool mightCompileFunctionForCall(CodeBlock*) { return false; }
293 inline bool mightCompileFunctionForConstruct(CodeBlock*) { return false; }
294 inline bool mightInlineFunctionForCall(CodeBlock*) { return false; }
295 inline bool mightInlineFunctionForConstruct(CodeBlock*) { return false; }
296
297 inline CapabilityLevel canCompileOpcode(OpcodeID, CodeBlock*, Instruction*) { return CannotCompile; }
298 inline bool canInlineOpcode(OpcodeID, CodeBlock*, Instruction*) { return false; }
299 inline CapabilityLevel canCompileOpcodes(CodeBlock*) { return CannotCompile; }
300 inline bool canInlineOpcodes(CodeBlock*) { return false; }
301 #endif // ENABLE(DFG_JIT)
302
303 inline CapabilityLevel canCompileEval(CodeBlock* codeBlock)
304 {
305     if (!mightCompileEval(codeBlock))
306         return CannotCompile;
307     
308     return canCompileOpcodes(codeBlock);
309 }
310
311 inline CapabilityLevel canCompileProgram(CodeBlock* codeBlock)
312 {
313     if (!mightCompileProgram(codeBlock))
314         return CannotCompile;
315     
316     return canCompileOpcodes(codeBlock);
317 }
318
319 inline CapabilityLevel canCompileFunctionForCall(CodeBlock* codeBlock)
320 {
321     if (!mightCompileFunctionForCall(codeBlock))
322         return CannotCompile;
323     
324     return canCompileOpcodes(codeBlock);
325 }
326
327 inline CapabilityLevel canCompileFunctionForConstruct(CodeBlock* codeBlock)
328 {
329     if (!mightCompileFunctionForConstruct(codeBlock))
330         return CannotCompile;
331     
332     return canCompileOpcodes(codeBlock);
333 }
334
335 inline bool canInlineFunctionForCall(CodeBlock* codeBlock)
336 {
337     return mightInlineFunctionForCall(codeBlock) && canInlineOpcodes(codeBlock);
338 }
339
340 inline bool canInlineFunctionForConstruct(CodeBlock* codeBlock)
341 {
342     return mightInlineFunctionForConstruct(codeBlock) && canInlineOpcodes(codeBlock);
343 }
344
345 inline bool mightInlineFunctionFor(CodeBlock* codeBlock, CodeSpecializationKind kind)
346 {
347     if (kind == CodeForCall)
348         return mightInlineFunctionForCall(codeBlock);
349     ASSERT(kind == CodeForConstruct);
350     return mightInlineFunctionForConstruct(codeBlock);
351 }
352
353 inline bool canInlineFunctionFor(CodeBlock* codeBlock, CodeSpecializationKind kind)
354 {
355     if (kind == CodeForCall)
356         return canInlineFunctionForCall(codeBlock);
357     ASSERT(kind == CodeForConstruct);
358     return canInlineFunctionForConstruct(codeBlock);
359 }
360
361 } } // namespace JSC::DFG
362
363 #endif // DFGCapabilities_h
364