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