2 * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
26 #ifndef DFGCapabilities_h
27 #define DFGCapabilities_h
29 #include "Intrinsic.h"
30 #include "DFGCommon.h"
32 #include "Executable.h"
34 #include "Interpreter.h"
35 #include <wtf/Platform.h>
37 namespace JSC { namespace DFG {
40 // Fast check functions; if they return true it is still necessary to
42 inline bool mightCompileEval(CodeBlock* codeBlock)
44 return codeBlock->instructionCount() <= Options::maximumOptimizationCandidateInstructionCount();
46 inline bool mightCompileProgram(CodeBlock* codeBlock)
48 return codeBlock->instructionCount() <= Options::maximumOptimizationCandidateInstructionCount();
50 inline bool mightCompileFunctionForCall(CodeBlock* codeBlock)
52 return codeBlock->instructionCount() <= Options::maximumOptimizationCandidateInstructionCount();
54 inline bool mightCompileFunctionForConstruct(CodeBlock* codeBlock)
56 return codeBlock->instructionCount() <= Options::maximumOptimizationCandidateInstructionCount();
59 inline bool mightInlineFunctionForCall(CodeBlock* codeBlock)
61 return codeBlock->instructionCount() <= Options::maximumFunctionForCallInlineCandidateInstructionCount()
62 && !codeBlock->ownerExecutable()->needsActivation();
64 inline bool mightInlineFunctionForConstruct(CodeBlock* codeBlock)
66 return codeBlock->instructionCount() <= Options::maximumFunctionForConstructInlineCandidateInstructionCount()
67 && !codeBlock->ownerExecutable()->needsActivation();
71 inline bool canInlineResolveOperations(OpcodeID opcode, ResolveOperations* operations)
73 // Don't try to inline a resolve for which we have no information
74 if (operations->isEmpty())
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:
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)
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.
105 case ResolveOperation::CheckForDynamicEntriesBeforeGlobalScope:
106 // This would be easy to support in all cases.
113 inline CapabilityLevel canCompileOpcode(OpcodeID opcodeID, CodeBlock*, Instruction*)
117 case op_convert_this:
136 #if ENABLE(DEBUG_WITH_BREAKPOINT)
140 case op_check_has_instance:
142 case op_is_undefined:
162 case op_get_by_id_out_of_line:
163 case op_get_array_length:
165 case op_put_by_id_out_of_line:
166 case op_put_by_id_transition_direct:
167 case op_put_by_id_transition_direct_out_of_line:
168 case op_put_by_id_transition_normal:
169 case op_put_by_id_transition_normal_out_of_line:
170 case op_init_global_const_nop:
171 case op_init_global_const:
172 case op_init_global_const_check:
177 case op_loop_if_true:
178 case op_loop_if_false:
190 case op_loop_if_less:
191 case op_loop_if_lesseq:
192 case op_loop_if_greater:
193 case op_loop_if_greatereq:
196 case op_call_put_result:
199 case op_new_array_with_size:
200 case op_new_array_buffer:
202 case op_to_primitive:
204 case op_throw_static_error:
208 case op_init_lazy_reg:
209 case op_create_activation:
210 case op_tear_off_activation:
211 case op_create_arguments:
212 case op_tear_off_arguments:
214 case op_new_func_exp:
215 case op_get_argument_by_val:
216 case op_get_arguments_length:
218 case op_put_to_base_variable:
222 case op_call_varargs:
223 return ShouldProfile;
226 case op_resolve_global_property:
227 case op_resolve_global_var:
228 case op_resolve_scoped_var:
229 case op_resolve_scoped_var_on_top_scope:
230 case op_resolve_scoped_var_with_top_scope_check:
233 case op_resolve_base_to_global:
234 case op_resolve_base_to_global_dynamic:
235 case op_resolve_base_to_scope:
236 case op_resolve_base_to_scope_with_top_scope_check:
237 case op_resolve_base:
238 case op_resolve_with_base:
239 case op_resolve_with_this:
243 return CannotCompile;
247 inline bool canInlineOpcode(OpcodeID opcodeID, CodeBlock* codeBlock, Instruction* pc)
251 case op_resolve_global_property:
252 case op_resolve_global_var:
253 case op_resolve_scoped_var:
254 case op_resolve_scoped_var_on_top_scope:
255 case op_resolve_scoped_var_with_top_scope_check:
256 return canInlineResolveOperations(opcodeID, codeBlock->resolveOperations(pc[3].u.operand));
258 case op_resolve_base_to_global:
259 case op_resolve_base_to_global_dynamic:
260 case op_resolve_base_to_scope:
261 case op_resolve_base_to_scope_with_top_scope_check:
262 case op_resolve_base:
263 case op_resolve_with_base:
264 case op_resolve_with_this:
265 return canInlineResolveOperations(opcodeID, codeBlock->resolveOperations(pc[4].u.operand));
267 // Inlining doesn't correctly remap regular expression operands.
270 // We don't support inlining code that creates activations or has nested functions.
271 case op_create_activation:
272 case op_tear_off_activation:
274 case op_new_func_exp:
277 // Inlining supports op_call_varargs if it's a call that just forwards the caller's
279 case op_call_varargs:
280 return codeBlock->usesArguments() && pc[3].u.operand == codeBlock->argumentsRegister();
283 return canCompileOpcode(opcodeID, codeBlock, pc) == CanCompile;
287 CapabilityLevel canCompileOpcodes(CodeBlock*);
288 bool canInlineOpcodes(CodeBlock*);
289 #else // ENABLE(DFG_JIT)
290 inline bool mightCompileEval(CodeBlock*) { return false; }
291 inline bool mightCompileProgram(CodeBlock*) { return false; }
292 inline bool mightCompileFunctionForCall(CodeBlock*) { return false; }
293 inline bool mightCompileFunctionForConstruct(CodeBlock*) { return false; }
294 inline bool mightInlineFunctionForCall(CodeBlock*) { return false; }
295 inline bool mightInlineFunctionForConstruct(CodeBlock*) { return false; }
297 inline CapabilityLevel canCompileOpcode(OpcodeID, CodeBlock*, Instruction*) { return CannotCompile; }
298 inline bool canInlineOpcode(OpcodeID, CodeBlock*, Instruction*) { return false; }
299 inline CapabilityLevel canCompileOpcodes(CodeBlock*) { return CannotCompile; }
300 inline bool canInlineOpcodes(CodeBlock*) { return false; }
301 #endif // ENABLE(DFG_JIT)
303 inline CapabilityLevel canCompileEval(CodeBlock* codeBlock)
305 if (!mightCompileEval(codeBlock))
306 return CannotCompile;
308 return canCompileOpcodes(codeBlock);
311 inline CapabilityLevel canCompileProgram(CodeBlock* codeBlock)
313 if (!mightCompileProgram(codeBlock))
314 return CannotCompile;
316 return canCompileOpcodes(codeBlock);
319 inline CapabilityLevel canCompileFunctionForCall(CodeBlock* codeBlock)
321 if (!mightCompileFunctionForCall(codeBlock))
322 return CannotCompile;
324 return canCompileOpcodes(codeBlock);
327 inline CapabilityLevel canCompileFunctionForConstruct(CodeBlock* codeBlock)
329 if (!mightCompileFunctionForConstruct(codeBlock))
330 return CannotCompile;
332 return canCompileOpcodes(codeBlock);
335 inline bool canInlineFunctionForCall(CodeBlock* codeBlock)
337 return mightInlineFunctionForCall(codeBlock) && canInlineOpcodes(codeBlock);
340 inline bool canInlineFunctionForConstruct(CodeBlock* codeBlock)
342 return mightInlineFunctionForConstruct(codeBlock) && canInlineOpcodes(codeBlock);
345 inline bool mightInlineFunctionFor(CodeBlock* codeBlock, CodeSpecializationKind kind)
347 if (kind == CodeForCall)
348 return mightInlineFunctionForCall(codeBlock);
349 ASSERT(kind == CodeForConstruct);
350 return mightInlineFunctionForConstruct(codeBlock);
353 inline bool canInlineFunctionFor(CodeBlock* codeBlock, CodeSpecializationKind kind)
355 if (kind == CodeForCall)
356 return canInlineFunctionForCall(codeBlock);
357 ASSERT(kind == CodeForConstruct);
358 return canInlineFunctionForConstruct(codeBlock);
361 } } // namespace JSC::DFG
363 #endif // DFGCapabilities_h