]> git.saurik.com Git - apple/javascriptcore.git/blame - dfg/DFGCapabilities.h
JavaScriptCore-1218.tar.gz
[apple/javascriptcore.git] / dfg / DFGCapabilities.h
CommitLineData
6fe7ccc8 1/*
93a37866 2 * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
6fe7ccc8
A
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"
93a37866 30#include "DFGCommon.h"
6fe7ccc8
A
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.
93a37866
A
42bool mightCompileEval(CodeBlock*);
43bool mightCompileProgram(CodeBlock*);
44bool mightCompileFunctionForCall(CodeBlock*);
45bool mightCompileFunctionForConstruct(CodeBlock*);
46bool mightInlineFunctionForCall(CodeBlock*);
47bool mightInlineFunctionForClosureCall(CodeBlock*);
48bool mightInlineFunctionForConstruct(CodeBlock*);
6fe7ccc8 49
93a37866
A
50// Opcode checking.
51inline bool canInlineResolveOperations(ResolveOperations* operations)
6fe7ccc8 52{
93a37866
A
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;
6fe7ccc8
A
83}
84
93a37866 85inline CapabilityLevel canCompileOpcode(OpcodeID opcodeID, CodeBlock*, Instruction*)
6fe7ccc8
A
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:
93a37866
A
98 case op_inc:
99 case op_dec:
6fe7ccc8
A
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:
6fe7ccc8 131 case op_get_by_id:
93a37866
A
132 case op_get_by_id_out_of_line:
133 case op_get_array_length:
6fe7ccc8 134 case op_put_by_id:
93a37866 135 case op_put_by_id_out_of_line:
6fe7ccc8 136 case op_put_by_id_transition_direct:
93a37866 137 case op_put_by_id_transition_direct_out_of_line:
6fe7ccc8 138 case op_put_by_id_transition_normal:
93a37866
A
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:
6fe7ccc8 143 case op_jmp:
6fe7ccc8
A
144 case op_jtrue:
145 case op_jfalse:
6fe7ccc8
A
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:
6fe7ccc8
A
157 case op_ret:
158 case op_end:
159 case op_call_put_result:
6fe7ccc8
A
160 case op_new_object:
161 case op_new_array:
93a37866 162 case op_new_array_with_size:
6fe7ccc8
A
163 case op_new_array_buffer:
164 case op_strcat:
165 case op_to_primitive:
166 case op_throw:
93a37866 167 case op_throw_static_error:
6fe7ccc8
A
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:
93a37866
A
174 case op_create_arguments:
175 case op_tear_off_arguments:
6fe7ccc8
A
176 case op_new_func:
177 case op_new_func_exp:
93a37866
A
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;
6fe7ccc8 186
93a37866
A
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
6fe7ccc8 211 default:
93a37866 212 return CannotCompile;
6fe7ccc8
A
213 }
214}
215
93a37866 216inline bool canInlineOpcode(OpcodeID opcodeID, CodeBlock* codeBlock, Instruction* pc)
6fe7ccc8
A
217{
218 switch (opcodeID) {
6fe7ccc8 219 case op_resolve:
93a37866
A
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:
6fe7ccc8 231 case op_resolve_base:
93a37866
A
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
6fe7ccc8
A
240 // Inlining doesn't correctly remap regular expression operands.
241 case op_new_regexp:
6fe7ccc8
A
242
243 // We don't support inlining code that creates activations or has nested functions.
6fe7ccc8
A
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
93a37866
A
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
6fe7ccc8 255 default:
93a37866 256 return canCompileOpcode(opcodeID, codeBlock, pc) == CanCompile;
6fe7ccc8
A
257 }
258}
259
93a37866 260CapabilityLevel canCompileOpcodes(CodeBlock*);
6fe7ccc8
A
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; }
93a37866 268inline bool mightInlineFunctionForClosureCall(CodeBlock*) { return false; }
6fe7ccc8
A
269inline bool mightInlineFunctionForConstruct(CodeBlock*) { return false; }
270
93a37866
A
271inline CapabilityLevel canCompileOpcode(OpcodeID, CodeBlock*, Instruction*) { return CannotCompile; }
272inline bool canInlineOpcode(OpcodeID, CodeBlock*, Instruction*) { return false; }
273inline CapabilityLevel canCompileOpcodes(CodeBlock*) { return CannotCompile; }
6fe7ccc8
A
274inline bool canInlineOpcodes(CodeBlock*) { return false; }
275#endif // ENABLE(DFG_JIT)
276
93a37866 277inline CapabilityLevel canCompileEval(CodeBlock* codeBlock)
6fe7ccc8 278{
93a37866
A
279 if (!mightCompileEval(codeBlock))
280 return CannotCompile;
281
282 return canCompileOpcodes(codeBlock);
6fe7ccc8
A
283}
284
93a37866 285inline CapabilityLevel canCompileProgram(CodeBlock* codeBlock)
6fe7ccc8 286{
93a37866
A
287 if (!mightCompileProgram(codeBlock))
288 return CannotCompile;
289
290 return canCompileOpcodes(codeBlock);
6fe7ccc8
A
291}
292
93a37866 293inline CapabilityLevel canCompileFunctionForCall(CodeBlock* codeBlock)
6fe7ccc8 294{
93a37866
A
295 if (!mightCompileFunctionForCall(codeBlock))
296 return CannotCompile;
297
298 return canCompileOpcodes(codeBlock);
6fe7ccc8
A
299}
300
93a37866 301inline CapabilityLevel canCompileFunctionForConstruct(CodeBlock* codeBlock)
6fe7ccc8 302{
93a37866
A
303 if (!mightCompileFunctionForConstruct(codeBlock))
304 return CannotCompile;
305
306 return canCompileOpcodes(codeBlock);
6fe7ccc8
A
307}
308
309inline bool canInlineFunctionForCall(CodeBlock* codeBlock)
310{
311 return mightInlineFunctionForCall(codeBlock) && canInlineOpcodes(codeBlock);
312}
313
93a37866
A
314inline bool canInlineFunctionForClosureCall(CodeBlock* codeBlock)
315{
316 return mightInlineFunctionForClosureCall(codeBlock) && canInlineOpcodes(codeBlock);
317}
318
6fe7ccc8
A
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
93a37866 332inline bool canInlineFunctionFor(CodeBlock* codeBlock, CodeSpecializationKind kind, bool isClosureCall)
6fe7ccc8 333{
93a37866
A
334 if (isClosureCall) {
335 ASSERT(kind == CodeForCall);
336 return canInlineFunctionForClosureCall(codeBlock);
337 }
6fe7ccc8
A
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