e339714e9132f8ca0730f1a244906101658ef19f
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGCapabilities.h
1 /*
2  * Copyright (C) 2011 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 "DFGNode.h"
31 #include "Executable.h"
32 #include "Options.h"
33 #include "Interpreter.h"
34 #include <wtf/Platform.h>
35
36 namespace JSC { namespace DFG {
37
38 #if ENABLE(DFG_JIT)
39 // Fast check functions; if they return true it is still necessary to
40 // check opcodes.
41 inline bool mightCompileEval(CodeBlock* codeBlock)
42 {
43     return codeBlock->instructionCount() <= Options::maximumOptimizationCandidateInstructionCount;
44 }
45 inline bool mightCompileProgram(CodeBlock* codeBlock)
46 {
47     return codeBlock->instructionCount() <= Options::maximumOptimizationCandidateInstructionCount;
48 }
49 inline bool mightCompileFunctionForCall(CodeBlock* codeBlock)
50 {
51     return codeBlock->instructionCount() <= Options::maximumOptimizationCandidateInstructionCount;
52 }
53 inline bool mightCompileFunctionForConstruct(CodeBlock* codeBlock)
54 {
55     return codeBlock->instructionCount() <= Options::maximumOptimizationCandidateInstructionCount;
56 }
57
58 inline bool mightInlineFunctionForCall(CodeBlock* codeBlock)
59 {
60     return codeBlock->instructionCount() <= Options::maximumFunctionForCallInlineCandidateInstructionCount;
61 }
62 inline bool mightInlineFunctionForConstruct(CodeBlock* codeBlock)
63 {
64     return codeBlock->instructionCount() <= Options::maximumFunctionForConstructInlineCandidateInstructionCount;
65 }
66
67 // Opcode checking.
68 inline bool canCompileOpcode(OpcodeID opcodeID)
69 {
70     switch (opcodeID) {
71     case op_enter:
72     case op_convert_this:
73     case op_create_this:
74     case op_get_callee:
75     case op_bitand:
76     case op_bitor:
77     case op_bitxor:
78     case op_rshift:
79     case op_lshift:
80     case op_urshift:
81     case op_pre_inc:
82     case op_post_inc:
83     case op_pre_dec:
84     case op_post_dec:
85     case op_add:
86     case op_sub:
87     case op_mul:
88     case op_mod:
89     case op_div:
90 #if ENABLE(DEBUG_WITH_BREAKPOINT)
91     case op_debug:
92 #endif
93     case op_mov:
94     case op_check_has_instance:
95     case op_instanceof:
96     case op_not:
97     case op_less:
98     case op_lesseq:
99     case op_greater:
100     case op_greatereq:
101     case op_eq:
102     case op_eq_null:
103     case op_stricteq:
104     case op_neq:
105     case op_neq_null:
106     case op_nstricteq:
107     case op_get_by_val:
108     case op_put_by_val:
109     case op_method_check:
110     case op_get_scoped_var:
111     case op_put_scoped_var:
112     case op_get_by_id:
113     case op_put_by_id:
114     case op_put_by_id_transition_direct:
115     case op_put_by_id_transition_normal:
116     case op_get_global_var:
117     case op_put_global_var:
118     case op_jmp:
119     case op_loop:
120     case op_jtrue:
121     case op_jfalse:
122     case op_loop_if_true:
123     case op_loop_if_false:
124     case op_jeq_null:
125     case op_jneq_null:
126     case op_jless:
127     case op_jlesseq:
128     case op_jgreater:
129     case op_jgreatereq:
130     case op_jnless:
131     case op_jnlesseq:
132     case op_jngreater:
133     case op_jngreatereq:
134     case op_loop_hint:
135     case op_loop_if_less:
136     case op_loop_if_lesseq:
137     case op_loop_if_greater:
138     case op_loop_if_greatereq:
139     case op_ret:
140     case op_end:
141     case op_call_put_result:
142     case op_resolve:
143     case op_resolve_base:
144     case op_resolve_global:
145     case op_new_object:
146     case op_new_array:
147     case op_new_array_buffer:
148     case op_strcat:
149     case op_to_primitive:
150     case op_throw:
151     case op_throw_reference_error:
152     case op_call:
153     case op_construct:
154         return true;
155         
156     // Opcodes we support conditionally. Enabling these opcodes currently results in
157     // performance regressions. Each node that we disable under restrictions has a
158     // comment describing what we know about the regression so far.
159         
160     // Regresses string-validate-input, probably because it uses comparisons (< and >)
161     // on strings, which currently will cause speculation failures in some cases.
162     case op_new_regexp: 
163 #if DFG_ENABLE(RESTRICTIONS)
164         return false;
165 #else
166         return true;
167 #endif
168       
169     default:
170         return false;
171     }
172 }
173
174 inline bool canInlineOpcode(OpcodeID opcodeID)
175 {
176     switch (opcodeID) {
177         
178     // These opcodes would be easy to support with inlining, but we currently don't do it.
179     // The issue is that the scope chain will not be set correctly.
180     case op_get_scoped_var:
181     case op_put_scoped_var:
182     case op_resolve:
183     case op_resolve_base:
184     case op_resolve_global:
185         
186     // Constant buffers aren't copied correctly. This is easy to fix, but for
187     // now we just disable inlining for functions that use them.
188     case op_new_array_buffer:
189         
190     // Inlining doesn't correctly remap regular expression operands.
191     case op_new_regexp:
192         return false;
193         
194     default:
195         return canCompileOpcode(opcodeID);
196     }
197 }
198
199 bool canCompileOpcodes(CodeBlock*);
200 bool canInlineOpcodes(CodeBlock*);
201 #else // ENABLE(DFG_JIT)
202 inline bool mightCompileEval(CodeBlock*) { return false; }
203 inline bool mightCompileProgram(CodeBlock*) { return false; }
204 inline bool mightCompileFunctionForCall(CodeBlock*) { return false; }
205 inline bool mightCompileFunctionForConstruct(CodeBlock*) { return false; }
206 inline bool mightInlineFunctionForCall(CodeBlock*) { return false; }
207 inline bool mightInlineFunctionForConstruct(CodeBlock*) { return false; }
208
209 inline bool canCompileOpcode(OpcodeID) { return false; }
210 inline bool canInlineOpcode(OpcodeID) { return false; }
211 inline bool canCompileOpcodes(CodeBlock*) { return false; }
212 inline bool canInlineOpcodes(CodeBlock*) { return false; }
213 #endif // ENABLE(DFG_JIT)
214
215 inline bool canCompileEval(CodeBlock* codeBlock)
216 {
217     return mightCompileEval(codeBlock) && canCompileOpcodes(codeBlock);
218 }
219
220 inline bool canCompileProgram(CodeBlock* codeBlock)
221 {
222     return mightCompileProgram(codeBlock) && canCompileOpcodes(codeBlock);
223 }
224
225 inline bool canCompileFunctionForCall(CodeBlock* codeBlock)
226 {
227     return mightCompileFunctionForCall(codeBlock) && canCompileOpcodes(codeBlock);
228 }
229
230 inline bool canCompileFunctionForConstruct(CodeBlock* codeBlock)
231 {
232     return mightCompileFunctionForConstruct(codeBlock) && canCompileOpcodes(codeBlock);
233 }
234
235 inline bool canInlineFunctionForCall(CodeBlock* codeBlock)
236 {
237     return mightInlineFunctionForCall(codeBlock) && canInlineOpcodes(codeBlock);
238 }
239
240 inline bool canInlineFunctionForConstruct(CodeBlock* codeBlock)
241 {
242     return mightInlineFunctionForConstruct(codeBlock) && canInlineOpcodes(codeBlock);
243 }
244
245 inline bool mightInlineFunctionFor(CodeBlock* codeBlock, CodeSpecializationKind kind)
246 {
247     if (kind == CodeForCall)
248         return mightInlineFunctionForCall(codeBlock);
249     ASSERT(kind == CodeForConstruct);
250     return mightInlineFunctionForConstruct(codeBlock);
251 }
252
253 inline bool canInlineFunctionFor(CodeBlock* codeBlock, CodeSpecializationKind kind)
254 {
255     if (kind == CodeForCall)
256         return canInlineFunctionForCall(codeBlock);
257     ASSERT(kind == CodeForConstruct);
258     return canInlineFunctionForConstruct(codeBlock);
259 }
260
261 } } // namespace JSC::DFG
262
263 #endif // DFGCapabilities_h
264