Fix TIVI-504 (backport of trac.webkit.org/changeset/144137)
[profile/ivi/webkit-efl.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 CapabilityLevel canCompileOpcode(OpcodeID opcodeID, CodeBlock*, Instruction*)
72 {
73     switch (opcodeID) {
74     case op_enter:
75     case op_convert_this:
76     case op_create_this:
77     case op_bitand:
78     case op_bitor:
79     case op_bitxor:
80     case op_rshift:
81     case op_lshift:
82     case op_urshift:
83     case op_pre_inc:
84     case op_post_inc:
85     case op_pre_dec:
86     case op_post_dec:
87     case op_add:
88     case op_sub:
89     case op_negate:
90     case op_mul:
91     case op_mod:
92     case op_div:
93 #if ENABLE(DEBUG_WITH_BREAKPOINT)
94     case op_debug:
95 #endif
96     case op_mov:
97     case op_check_has_instance:
98     case op_instanceof:
99     case op_is_undefined:
100     case op_is_boolean:
101     case op_is_number:
102     case op_is_string:
103     case op_is_object:
104     case op_is_function:
105     case op_not:
106     case op_less:
107     case op_lesseq:
108     case op_greater:
109     case op_greatereq:
110     case op_eq:
111     case op_eq_null:
112     case op_stricteq:
113     case op_neq:
114     case op_neq_null:
115     case op_nstricteq:
116     case op_get_by_val:
117     case op_put_by_val:
118     case op_method_check:
119     case op_get_scoped_var:
120     case op_put_scoped_var:
121     case op_get_by_id:
122     case op_put_by_id:
123     case op_put_by_id_transition_direct:
124     case op_put_by_id_transition_normal:
125     case op_get_global_var:
126     case op_put_global_var:
127     case op_jmp:
128     case op_loop:
129     case op_jtrue:
130     case op_jfalse:
131     case op_loop_if_true:
132     case op_loop_if_false:
133     case op_jeq_null:
134     case op_jneq_null:
135     case op_jless:
136     case op_jlesseq:
137     case op_jgreater:
138     case op_jgreatereq:
139     case op_jnless:
140     case op_jnlesseq:
141     case op_jngreater:
142     case op_jngreatereq:
143     case op_loop_hint:
144     case op_loop_if_less:
145     case op_loop_if_lesseq:
146     case op_loop_if_greater:
147     case op_loop_if_greatereq:
148     case op_ret:
149     case op_end:
150     case op_call_put_result:
151     case op_resolve:
152     case op_resolve_base:
153     case op_resolve_global:
154     case op_new_object:
155     case op_new_array:
156     case op_new_array_buffer:
157     case op_strcat:
158     case op_to_primitive:
159     case op_throw:
160     case op_throw_reference_error:
161     case op_call:
162     case op_construct:
163     case op_new_regexp: 
164     case op_init_lazy_reg:
165     case op_create_activation:
166     case op_tear_off_activation:
167     case op_create_arguments:
168     case op_tear_off_arguments:
169     case op_new_func:
170     case op_new_func_exp:
171     case op_get_argument_by_val:
172     case op_get_arguments_length:
173     case op_jneq_ptr:
174         return CanCompile;
175         
176     case op_call_varargs:
177         return MayInline;
178
179     default:
180         return CannotCompile;
181     }
182 }
183
184 inline bool canInlineOpcode(OpcodeID opcodeID, CodeBlock* codeBlock, Instruction* pc)
185 {
186     switch (opcodeID) {
187         
188     // These opcodes would be easy to support with inlining, but we currently don't do it.
189     // The issue is that the scope chain will not be set correctly.
190     case op_get_scoped_var:
191     case op_put_scoped_var:
192     case op_resolve:
193     case op_resolve_base:
194     case op_resolve_global:
195         
196     // Constant buffers aren't copied correctly. This is easy to fix, but for
197     // now we just disable inlining for functions that use them.
198     case op_new_array_buffer:
199         
200     // Inlining doesn't correctly remap regular expression operands.
201     case op_new_regexp:
202         
203     // We don't support inlining code that creates activations or has nested functions.
204     case op_create_activation:
205     case op_tear_off_activation:
206     case op_new_func:
207     case op_new_func_exp:
208         return false;
209         
210     // Inlining supports op_call_varargs if it's a call that just forwards the caller's
211     // arguments.
212     case op_call_varargs:
213         return codeBlock->usesArguments() && pc[3].u.operand == codeBlock->argumentsRegister();
214         
215     default:
216         return canCompileOpcode(opcodeID, codeBlock, pc) == CanCompile;
217     }
218 }
219
220 CapabilityLevel canCompileOpcodes(CodeBlock*);
221 bool canInlineOpcodes(CodeBlock*);
222 #else // ENABLE(DFG_JIT)
223 inline bool mightCompileEval(CodeBlock*) { return false; }
224 inline bool mightCompileProgram(CodeBlock*) { return false; }
225 inline bool mightCompileFunctionForCall(CodeBlock*) { return false; }
226 inline bool mightCompileFunctionForConstruct(CodeBlock*) { return false; }
227 inline bool mightInlineFunctionForCall(CodeBlock*) { return false; }
228 inline bool mightInlineFunctionForConstruct(CodeBlock*) { return false; }
229
230 inline CapabilityLevel canCompileOpcode(OpcodeID, CodeBlock*, Instruction*) { return CannotCompile; }
231 inline bool canInlineOpcode(OpcodeID, CodeBlock*, Instruction*) { return false; }
232 inline CapabilityLevel canCompileOpcodes(CodeBlock*) { return CannotCompile; }
233 inline bool canInlineOpcodes(CodeBlock*) { return false; }
234 #endif // ENABLE(DFG_JIT)
235
236 inline CapabilityLevel canCompileEval(CodeBlock* codeBlock)
237 {
238     if (!mightCompileEval(codeBlock))
239         return CannotCompile;
240     
241     return canCompileOpcodes(codeBlock);
242 }
243
244 inline CapabilityLevel canCompileProgram(CodeBlock* codeBlock)
245 {
246     if (!mightCompileProgram(codeBlock))
247         return CannotCompile;
248     
249     return canCompileOpcodes(codeBlock);
250 }
251
252 inline CapabilityLevel canCompileFunctionForCall(CodeBlock* codeBlock)
253 {
254     if (!mightCompileFunctionForCall(codeBlock))
255         return CannotCompile;
256     
257     return canCompileOpcodes(codeBlock);
258 }
259
260 inline CapabilityLevel canCompileFunctionForConstruct(CodeBlock* codeBlock)
261 {
262     if (!mightCompileFunctionForConstruct(codeBlock))
263         return CannotCompile;
264     
265     return canCompileOpcodes(codeBlock);
266 }
267
268 inline bool canInlineFunctionForCall(CodeBlock* codeBlock)
269 {
270     return mightInlineFunctionForCall(codeBlock) && canInlineOpcodes(codeBlock);
271 }
272
273 inline bool canInlineFunctionForConstruct(CodeBlock* codeBlock)
274 {
275     return mightInlineFunctionForConstruct(codeBlock) && canInlineOpcodes(codeBlock);
276 }
277
278 inline bool mightInlineFunctionFor(CodeBlock* codeBlock, CodeSpecializationKind kind)
279 {
280     if (kind == CodeForCall)
281         return mightInlineFunctionForCall(codeBlock);
282     ASSERT(kind == CodeForConstruct);
283     return mightInlineFunctionForConstruct(codeBlock);
284 }
285
286 inline bool canInlineFunctionFor(CodeBlock* codeBlock, CodeSpecializationKind kind)
287 {
288     if (kind == CodeForCall)
289         return canInlineFunctionForCall(codeBlock);
290     ASSERT(kind == CodeForConstruct);
291     return canInlineFunctionForConstruct(codeBlock);
292 }
293
294 } } // namespace JSC::DFG
295
296 #endif // DFGCapabilities_h
297