Get rid of method_check
[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_bitand:
120     case op_bitor:
121     case op_bitxor:
122     case op_rshift:
123     case op_lshift:
124     case op_urshift:
125     case op_pre_inc:
126     case op_post_inc:
127     case op_pre_dec:
128     case op_post_dec:
129     case op_add:
130     case op_sub:
131     case op_negate:
132     case op_mul:
133     case op_mod:
134     case op_div:
135 #if ENABLE(DEBUG_WITH_BREAKPOINT)
136     case op_debug:
137 #endif
138     case op_mov:
139     case op_check_has_instance:
140     case op_instanceof:
141     case op_is_undefined:
142     case op_is_boolean:
143     case op_is_number:
144     case op_is_string:
145     case op_is_object:
146     case op_is_function:
147     case op_not:
148     case op_less:
149     case op_lesseq:
150     case op_greater:
151     case op_greatereq:
152     case op_eq:
153     case op_eq_null:
154     case op_stricteq:
155     case op_neq:
156     case op_neq_null:
157     case op_nstricteq:
158     case op_get_by_val:
159     case op_put_by_val:
160     case op_get_by_id:
161     case op_get_by_id_out_of_line:
162     case op_get_array_length:
163     case op_put_by_id:
164     case op_put_by_id_out_of_line:
165     case op_put_by_id_transition_direct:
166     case op_put_by_id_transition_direct_out_of_line:
167     case op_put_by_id_transition_normal:
168     case op_put_by_id_transition_normal_out_of_line:
169     case op_init_global_const:
170     case op_init_global_const_check:
171     case op_jmp:
172     case op_loop:
173     case op_jtrue:
174     case op_jfalse:
175     case op_loop_if_true:
176     case op_loop_if_false:
177     case op_jeq_null:
178     case op_jneq_null:
179     case op_jless:
180     case op_jlesseq:
181     case op_jgreater:
182     case op_jgreatereq:
183     case op_jnless:
184     case op_jnlesseq:
185     case op_jngreater:
186     case op_jngreatereq:
187     case op_loop_hint:
188     case op_loop_if_less:
189     case op_loop_if_lesseq:
190     case op_loop_if_greater:
191     case op_loop_if_greatereq:
192     case op_ret:
193     case op_end:
194     case op_call_put_result:
195     case op_new_object:
196     case op_new_array:
197     case op_new_array_with_size:
198     case op_new_array_buffer:
199     case op_strcat:
200     case op_to_primitive:
201     case op_throw:
202     case op_throw_reference_error:
203     case op_call:
204     case op_construct:
205     case op_new_regexp: 
206     case op_init_lazy_reg:
207     case op_create_activation:
208     case op_tear_off_activation:
209     case op_create_arguments:
210     case op_tear_off_arguments:
211     case op_new_func:
212     case op_new_func_exp:
213     case op_get_argument_by_val:
214     case op_get_arguments_length:
215     case op_jneq_ptr:
216     case op_put_to_base_variable:
217     case op_put_to_base:
218         return CanCompile;
219         
220     case op_call_varargs:
221         return ShouldProfile;
222
223     case op_resolve:
224     case op_resolve_global_property:
225     case op_resolve_global_var:
226     case op_resolve_scoped_var:
227     case op_resolve_scoped_var_on_top_scope:
228     case op_resolve_scoped_var_with_top_scope_check:
229         return CanCompile;
230
231     case op_resolve_base_to_global:
232     case op_resolve_base_to_global_dynamic:
233     case op_resolve_base_to_scope:
234     case op_resolve_base_to_scope_with_top_scope_check:
235     case op_resolve_base:
236     case op_resolve_with_base:
237     case op_resolve_with_this:
238         return CanCompile;
239
240     default:
241         return CannotCompile;
242     }
243 }
244
245 inline bool canInlineOpcode(OpcodeID opcodeID, CodeBlock* codeBlock, Instruction* pc)
246 {
247     switch (opcodeID) {
248     case op_resolve:
249     case op_resolve_global_property:
250     case op_resolve_global_var:
251     case op_resolve_scoped_var:
252     case op_resolve_scoped_var_on_top_scope:
253     case op_resolve_scoped_var_with_top_scope_check:
254         return canInlineResolveOperations(opcodeID, codeBlock->resolveOperations(pc[3].u.operand));
255
256     case op_resolve_base_to_global:
257     case op_resolve_base_to_global_dynamic:
258     case op_resolve_base_to_scope:
259     case op_resolve_base_to_scope_with_top_scope_check:
260     case op_resolve_base:
261     case op_resolve_with_base:
262     case op_resolve_with_this:
263         return canInlineResolveOperations(opcodeID, codeBlock->resolveOperations(pc[4].u.operand));
264         
265     // Inlining doesn't correctly remap regular expression operands.
266     case op_new_regexp:
267         
268     // We don't support inlining code that creates activations or has nested functions.
269     case op_create_activation:
270     case op_tear_off_activation:
271     case op_new_func:
272     case op_new_func_exp:
273         return false;
274         
275     // Inlining supports op_call_varargs if it's a call that just forwards the caller's
276     // arguments.
277     case op_call_varargs:
278         return codeBlock->usesArguments() && pc[3].u.operand == codeBlock->argumentsRegister();
279         
280     default:
281         return canCompileOpcode(opcodeID, codeBlock, pc) == CanCompile;
282     }
283 }
284
285 CapabilityLevel canCompileOpcodes(CodeBlock*);
286 bool canInlineOpcodes(CodeBlock*);
287 #else // ENABLE(DFG_JIT)
288 inline bool mightCompileEval(CodeBlock*) { return false; }
289 inline bool mightCompileProgram(CodeBlock*) { return false; }
290 inline bool mightCompileFunctionForCall(CodeBlock*) { return false; }
291 inline bool mightCompileFunctionForConstruct(CodeBlock*) { return false; }
292 inline bool mightInlineFunctionForCall(CodeBlock*) { return false; }
293 inline bool mightInlineFunctionForConstruct(CodeBlock*) { return false; }
294
295 inline CapabilityLevel canCompileOpcode(OpcodeID, CodeBlock*, Instruction*) { return CannotCompile; }
296 inline bool canInlineOpcode(OpcodeID, CodeBlock*, Instruction*) { return false; }
297 inline CapabilityLevel canCompileOpcodes(CodeBlock*) { return CannotCompile; }
298 inline bool canInlineOpcodes(CodeBlock*) { return false; }
299 #endif // ENABLE(DFG_JIT)
300
301 inline CapabilityLevel canCompileEval(CodeBlock* codeBlock)
302 {
303     if (!mightCompileEval(codeBlock))
304         return CannotCompile;
305     
306     return canCompileOpcodes(codeBlock);
307 }
308
309 inline CapabilityLevel canCompileProgram(CodeBlock* codeBlock)
310 {
311     if (!mightCompileProgram(codeBlock))
312         return CannotCompile;
313     
314     return canCompileOpcodes(codeBlock);
315 }
316
317 inline CapabilityLevel canCompileFunctionForCall(CodeBlock* codeBlock)
318 {
319     if (!mightCompileFunctionForCall(codeBlock))
320         return CannotCompile;
321     
322     return canCompileOpcodes(codeBlock);
323 }
324
325 inline CapabilityLevel canCompileFunctionForConstruct(CodeBlock* codeBlock)
326 {
327     if (!mightCompileFunctionForConstruct(codeBlock))
328         return CannotCompile;
329     
330     return canCompileOpcodes(codeBlock);
331 }
332
333 inline bool canInlineFunctionForCall(CodeBlock* codeBlock)
334 {
335     return mightInlineFunctionForCall(codeBlock) && canInlineOpcodes(codeBlock);
336 }
337
338 inline bool canInlineFunctionForConstruct(CodeBlock* codeBlock)
339 {
340     return mightInlineFunctionForConstruct(codeBlock) && canInlineOpcodes(codeBlock);
341 }
342
343 inline bool mightInlineFunctionFor(CodeBlock* codeBlock, CodeSpecializationKind kind)
344 {
345     if (kind == CodeForCall)
346         return mightInlineFunctionForCall(codeBlock);
347     ASSERT(kind == CodeForConstruct);
348     return mightInlineFunctionForConstruct(codeBlock);
349 }
350
351 inline bool canInlineFunctionFor(CodeBlock* codeBlock, CodeSpecializationKind kind)
352 {
353     if (kind == CodeForCall)
354         return canInlineFunctionForCall(codeBlock);
355     ASSERT(kind == CodeForConstruct);
356     return canInlineFunctionForConstruct(codeBlock);
357 }
358
359 } } // namespace JSC::DFG
360
361 #endif // DFGCapabilities_h
362