]> git.saurik.com Git - apple/javascriptcore.git/blob - dfg/DFGCapabilities.cpp
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / dfg / DFGCapabilities.cpp
1 /*
2 * Copyright (C) 2011, 2013-2015 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 #include "config.h"
27 #include "DFGCapabilities.h"
28
29 #if ENABLE(DFG_JIT)
30
31 #include "CodeBlock.h"
32 #include "DFGCommon.h"
33 #include "Interpreter.h"
34 #include "JSCInlines.h"
35 #include "Options.h"
36
37 namespace JSC { namespace DFG {
38
39 bool isSupported()
40 {
41 return Options::useDFGJIT()
42 && MacroAssembler::supportsFloatingPoint();
43 }
44
45 bool isSupportedForInlining(CodeBlock* codeBlock)
46 {
47 return codeBlock->ownerExecutable()->isInliningCandidate();
48 }
49
50 bool mightCompileEval(CodeBlock* codeBlock)
51 {
52 return isSupported()
53 && codeBlock->instructionCount() <= Options::maximumOptimizationCandidateInstructionCount();
54 }
55 bool mightCompileProgram(CodeBlock* codeBlock)
56 {
57 return isSupported()
58 && codeBlock->instructionCount() <= Options::maximumOptimizationCandidateInstructionCount();
59 }
60 bool mightCompileFunctionForCall(CodeBlock* codeBlock)
61 {
62 return isSupported()
63 && codeBlock->instructionCount() <= Options::maximumOptimizationCandidateInstructionCount();
64 }
65 bool mightCompileFunctionForConstruct(CodeBlock* codeBlock)
66 {
67 return isSupported()
68 && codeBlock->instructionCount() <= Options::maximumOptimizationCandidateInstructionCount();
69 }
70
71 bool mightInlineFunctionForCall(CodeBlock* codeBlock)
72 {
73 return codeBlock->instructionCount() <= Options::maximumFunctionForCallInlineCandidateInstructionCount()
74 && isSupportedForInlining(codeBlock);
75 }
76 bool mightInlineFunctionForClosureCall(CodeBlock* codeBlock)
77 {
78 return codeBlock->instructionCount() <= Options::maximumFunctionForClosureCallInlineCandidateInstructionCount()
79 && isSupportedForInlining(codeBlock);
80 }
81 bool mightInlineFunctionForConstruct(CodeBlock* codeBlock)
82 {
83 return codeBlock->instructionCount() <= Options::maximumFunctionForConstructInlineCandidateInstructionCount()
84 && isSupportedForInlining(codeBlock);
85 }
86
87 inline void debugFail(CodeBlock* codeBlock, OpcodeID opcodeID, CapabilityLevel result)
88 {
89 if (Options::verboseCompilation() && !canCompile(result))
90 dataLog("Cannot compile code block ", *codeBlock, " because of opcode ", opcodeNames[opcodeID], "\n");
91 }
92
93 CapabilityLevel capabilityLevel(OpcodeID opcodeID, CodeBlock* codeBlock, Instruction* pc)
94 {
95 UNUSED_PARAM(codeBlock); // This function does some bytecode parsing. Ordinarily bytecode parsing requires the owning CodeBlock. It's sort of strange that we don't use it here right now.
96
97 switch (opcodeID) {
98 case op_enter:
99 case op_to_this:
100 case op_check_tdz:
101 case op_create_this:
102 case op_bitand:
103 case op_bitor:
104 case op_bitxor:
105 case op_rshift:
106 case op_lshift:
107 case op_urshift:
108 case op_unsigned:
109 case op_inc:
110 case op_dec:
111 case op_add:
112 case op_sub:
113 case op_negate:
114 case op_mul:
115 case op_mod:
116 case op_div:
117 case op_debug:
118 case op_profile_will_call:
119 case op_profile_did_call:
120 case op_profile_type:
121 case op_profile_control_flow:
122 case op_mov:
123 case op_check_has_instance:
124 case op_instanceof:
125 case op_is_undefined:
126 case op_is_boolean:
127 case op_is_number:
128 case op_is_string:
129 case op_is_object:
130 case op_is_object_or_null:
131 case op_is_function:
132 case op_not:
133 case op_less:
134 case op_lesseq:
135 case op_greater:
136 case op_greatereq:
137 case op_eq:
138 case op_eq_null:
139 case op_stricteq:
140 case op_neq:
141 case op_neq_null:
142 case op_nstricteq:
143 case op_get_by_val:
144 case op_put_by_val:
145 case op_put_by_val_direct:
146 case op_get_by_id:
147 case op_get_by_id_out_of_line:
148 case op_get_array_length:
149 case op_put_by_id:
150 case op_put_by_id_out_of_line:
151 case op_put_by_id_transition_direct:
152 case op_put_by_id_transition_direct_out_of_line:
153 case op_put_by_id_transition_normal:
154 case op_put_by_id_transition_normal_out_of_line:
155 case op_init_global_const_nop:
156 case op_init_global_const:
157 case op_jmp:
158 case op_jtrue:
159 case op_jfalse:
160 case op_jeq_null:
161 case op_jneq_null:
162 case op_jless:
163 case op_jlesseq:
164 case op_jgreater:
165 case op_jgreatereq:
166 case op_jnless:
167 case op_jnlesseq:
168 case op_jngreater:
169 case op_jngreatereq:
170 case op_loop_hint:
171 case op_ret:
172 case op_end:
173 case op_new_object:
174 case op_new_array:
175 case op_new_array_with_size:
176 case op_new_array_buffer:
177 case op_strcat:
178 case op_to_primitive:
179 case op_throw:
180 case op_throw_static_error:
181 case op_call:
182 case op_construct:
183 case op_call_varargs:
184 case op_construct_varargs:
185 case op_create_direct_arguments:
186 case op_create_scoped_arguments:
187 case op_create_out_of_band_arguments:
188 case op_get_from_arguments:
189 case op_put_to_arguments:
190 case op_jneq_ptr:
191 case op_typeof:
192 case op_to_number:
193 case op_to_string:
194 case op_switch_imm:
195 case op_switch_char:
196 case op_in:
197 case op_get_scope:
198 case op_get_from_scope:
199 case op_get_enumerable_length:
200 case op_has_generic_property:
201 case op_has_structure_property:
202 case op_has_indexed_property:
203 case op_get_direct_pname:
204 case op_get_property_enumerator:
205 case op_enumerator_structure_pname:
206 case op_enumerator_generic_pname:
207 case op_to_index_string:
208 case op_new_func:
209 case op_new_func_exp:
210 case op_create_lexical_environment:
211 return CanCompileAndInline;
212
213 case op_put_to_scope: {
214 ResolveType resolveType = ResolveModeAndType(pc[4].u.operand).type();
215 // If we're writing to a readonly property we emit a Dynamic put that
216 // the DFG can't currently handle.
217 if (resolveType == Dynamic)
218 return CannotCompile;
219 return CanCompileAndInline;
220 }
221
222 case op_resolve_scope: {
223 // We don't compile 'catch' or 'with', so there's no point in compiling variable resolution within them.
224 ResolveType resolveType = ResolveModeAndType(pc[4].u.operand).type();
225 if (resolveType == Dynamic)
226 return CannotCompile;
227 return CanCompileAndInline;
228 }
229
230 case op_new_regexp:
231 case op_switch_string: // Don't inline because we don't want to copy string tables in the concurrent JIT.
232 return CanCompile;
233
234 default:
235 return CannotCompile;
236 }
237 }
238
239 CapabilityLevel capabilityLevel(CodeBlock* codeBlock)
240 {
241 Interpreter* interpreter = codeBlock->vm()->interpreter;
242 Instruction* instructionsBegin = codeBlock->instructions().begin();
243 unsigned instructionCount = codeBlock->instructions().size();
244 CapabilityLevel result = CanCompileAndInline;
245
246 for (unsigned bytecodeOffset = 0; bytecodeOffset < instructionCount; ) {
247 switch (interpreter->getOpcodeID(instructionsBegin[bytecodeOffset].u.opcode)) {
248 #define DEFINE_OP(opcode, length) \
249 case opcode: { \
250 CapabilityLevel newResult = leastUpperBound(result, capabilityLevel(opcode, codeBlock, instructionsBegin + bytecodeOffset)); \
251 if (newResult != result) { \
252 debugFail(codeBlock, opcode, newResult); \
253 result = newResult; \
254 } \
255 bytecodeOffset += length; \
256 break; \
257 }
258 FOR_EACH_OPCODE_ID(DEFINE_OP)
259 #undef DEFINE_OP
260 default:
261 RELEASE_ASSERT_NOT_REACHED();
262 break;
263 }
264 }
265
266 return result;
267 }
268
269 } } // namespace JSC::DFG
270
271 #endif