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