]> git.saurik.com Git - apple/javascriptcore.git/blob - bytecode/BytecodeUseDef.h
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / bytecode / BytecodeUseDef.h
1 /*
2 * Copyright (C) 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. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #ifndef BytecodeUseDef_h
27 #define BytecodeUseDef_h
28
29 #include "CodeBlock.h"
30
31 namespace JSC {
32
33 template<typename Functor>
34 void computeUsesForBytecodeOffset(
35 CodeBlock* codeBlock, unsigned bytecodeOffset, const Functor& functor)
36 {
37 Interpreter* interpreter = codeBlock->vm()->interpreter;
38 Instruction* instructionsBegin = codeBlock->instructions().begin();
39 Instruction* instruction = &instructionsBegin[bytecodeOffset];
40 OpcodeID opcodeID = interpreter->getOpcodeID(instruction->u.opcode);
41 switch (opcodeID) {
42 // No uses.
43 case op_new_regexp:
44 case op_new_array_buffer:
45 case op_throw_static_error:
46 case op_debug:
47 case op_jneq_ptr:
48 case op_loop_hint:
49 case op_jmp:
50 case op_new_object:
51 case op_enter:
52 case op_catch:
53 case op_profile_control_flow:
54 case op_create_direct_arguments:
55 case op_create_out_of_band_arguments:
56 return;
57 case op_get_scope:
58 case op_to_this:
59 case op_check_tdz:
60 case op_pop_scope:
61 case op_profile_will_call:
62 case op_profile_did_call:
63 case op_profile_type:
64 case op_throw:
65 case op_end:
66 case op_ret:
67 case op_jtrue:
68 case op_jfalse:
69 case op_jeq_null:
70 case op_jneq_null:
71 case op_dec:
72 case op_inc: {
73 functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
74 return;
75 }
76 case op_jlesseq:
77 case op_jgreater:
78 case op_jgreatereq:
79 case op_jnless:
80 case op_jnlesseq:
81 case op_jngreater:
82 case op_jngreatereq:
83 case op_jless: {
84 functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
85 functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
86 return;
87 }
88 case op_put_by_val_direct:
89 case op_put_by_val: {
90 functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
91 functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
92 functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
93 return;
94 }
95 case op_put_by_index:
96 case op_put_by_id_transition_direct:
97 case op_put_by_id_transition_direct_out_of_line:
98 case op_put_by_id_transition_normal:
99 case op_put_by_id_transition_normal_out_of_line:
100 case op_put_by_id_out_of_line:
101 case op_put_by_id:
102 case op_put_getter_by_id:
103 case op_put_setter_by_id:
104 case op_put_to_scope:
105 case op_put_to_arguments: {
106 functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
107 functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
108 return;
109 }
110 case op_put_getter_setter: {
111 functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
112 functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
113 functor(codeBlock, instruction, opcodeID, instruction[4].u.operand);
114 return;
115 }
116 case op_create_lexical_environment:
117 case op_get_property_enumerator:
118 case op_get_enumerable_length:
119 case op_new_func_exp:
120 case op_to_index_string:
121 case op_init_global_const_nop:
122 case op_init_global_const:
123 case op_push_name_scope:
124 case op_push_with_scope:
125 case op_resolve_scope:
126 case op_get_from_scope:
127 case op_to_primitive:
128 case op_get_by_id:
129 case op_get_by_id_out_of_line:
130 case op_get_array_length:
131 case op_typeof:
132 case op_is_undefined:
133 case op_is_boolean:
134 case op_is_number:
135 case op_is_string:
136 case op_is_object:
137 case op_is_object_or_null:
138 case op_is_function:
139 case op_to_number:
140 case op_to_string:
141 case op_negate:
142 case op_neq_null:
143 case op_eq_null:
144 case op_not:
145 case op_mov:
146 case op_new_array_with_size:
147 case op_create_this:
148 case op_del_by_id:
149 case op_unsigned:
150 case op_new_func:
151 case op_create_scoped_arguments:
152 case op_get_from_arguments: {
153 functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
154 return;
155 }
156 case op_has_generic_property:
157 case op_has_indexed_property:
158 case op_enumerator_structure_pname:
159 case op_enumerator_generic_pname:
160 case op_get_by_val:
161 case op_in:
162 case op_instanceof:
163 case op_check_has_instance:
164 case op_add:
165 case op_mul:
166 case op_div:
167 case op_mod:
168 case op_sub:
169 case op_lshift:
170 case op_rshift:
171 case op_urshift:
172 case op_bitand:
173 case op_bitxor:
174 case op_bitor:
175 case op_less:
176 case op_lesseq:
177 case op_greater:
178 case op_greatereq:
179 case op_nstricteq:
180 case op_stricteq:
181 case op_neq:
182 case op_eq:
183 case op_del_by_val: {
184 functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
185 functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
186 return;
187 }
188 case op_has_structure_property:
189 case op_construct_varargs:
190 case op_call_varargs: {
191 functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
192 functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
193 functor(codeBlock, instruction, opcodeID, instruction[4].u.operand);
194 return;
195 }
196 case op_get_direct_pname: {
197 functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
198 functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
199 functor(codeBlock, instruction, opcodeID, instruction[4].u.operand);
200 functor(codeBlock, instruction, opcodeID, instruction[5].u.operand);
201 return;
202 }
203 case op_switch_string:
204 case op_switch_char:
205 case op_switch_imm: {
206 functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
207 return;
208 }
209 case op_new_array:
210 case op_strcat: {
211 int base = instruction[2].u.operand;
212 int count = instruction[3].u.operand;
213 for (int i = 0; i < count; i++)
214 functor(codeBlock, instruction, opcodeID, base - i);
215 return;
216 }
217 case op_construct:
218 case op_call_eval:
219 case op_call: {
220 functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
221 int argCount = instruction[3].u.operand;
222 int registerOffset = -instruction[4].u.operand;
223 int lastArg = registerOffset + CallFrame::thisArgumentOffset();
224 for (int i = 0; i < argCount; i++)
225 functor(codeBlock, instruction, opcodeID, lastArg + i);
226 return;
227 }
228 default:
229 RELEASE_ASSERT_NOT_REACHED();
230 break;
231 }
232 }
233
234 template<typename Functor>
235 void computeDefsForBytecodeOffset(CodeBlock* codeBlock, unsigned bytecodeOffset, const Functor& functor)
236 {
237 Interpreter* interpreter = codeBlock->vm()->interpreter;
238 Instruction* instructionsBegin = codeBlock->instructions().begin();
239 Instruction* instruction = &instructionsBegin[bytecodeOffset];
240 OpcodeID opcodeID = interpreter->getOpcodeID(instruction->u.opcode);
241 switch (opcodeID) {
242 // These don't define anything.
243 case op_init_global_const:
244 case op_init_global_const_nop:
245 case op_put_to_scope:
246 case op_end:
247 case op_profile_will_call:
248 case op_profile_did_call:
249 case op_throw:
250 case op_throw_static_error:
251 case op_debug:
252 case op_ret:
253 case op_jmp:
254 case op_jtrue:
255 case op_jfalse:
256 case op_jeq_null:
257 case op_jneq_null:
258 case op_jneq_ptr:
259 case op_jless:
260 case op_jlesseq:
261 case op_jgreater:
262 case op_jgreatereq:
263 case op_jnless:
264 case op_jnlesseq:
265 case op_jngreater:
266 case op_jngreatereq:
267 case op_loop_hint:
268 case op_switch_imm:
269 case op_switch_char:
270 case op_switch_string:
271 case op_put_by_id:
272 case op_put_by_id_out_of_line:
273 case op_put_by_id_transition_direct:
274 case op_put_by_id_transition_direct_out_of_line:
275 case op_put_by_id_transition_normal:
276 case op_put_by_id_transition_normal_out_of_line:
277 case op_put_getter_by_id:
278 case op_put_setter_by_id:
279 case op_put_getter_setter:
280 case op_put_by_val:
281 case op_put_by_val_direct:
282 case op_put_by_index:
283 case op_profile_type:
284 case op_profile_control_flow:
285 case op_put_to_arguments:
286 #define LLINT_HELPER_OPCODES(opcode, length) case opcode:
287 FOR_EACH_LLINT_OPCODE_EXTENSION(LLINT_HELPER_OPCODES);
288 #undef LLINT_HELPER_OPCODES
289 return;
290 // These all have a single destination for the first argument.
291 case op_to_index_string:
292 case op_get_enumerable_length:
293 case op_has_indexed_property:
294 case op_has_structure_property:
295 case op_has_generic_property:
296 case op_get_direct_pname:
297 case op_get_property_enumerator:
298 case op_enumerator_structure_pname:
299 case op_enumerator_generic_pname:
300 case op_pop_scope:
301 case op_push_name_scope:
302 case op_push_with_scope:
303 case op_resolve_scope:
304 case op_strcat:
305 case op_to_primitive:
306 case op_create_this:
307 case op_new_array:
308 case op_new_array_buffer:
309 case op_new_array_with_size:
310 case op_new_regexp:
311 case op_new_func:
312 case op_new_func_exp:
313 case op_call_varargs:
314 case op_construct_varargs:
315 case op_get_from_scope:
316 case op_call:
317 case op_call_eval:
318 case op_construct:
319 case op_get_by_id:
320 case op_get_by_id_out_of_line:
321 case op_get_array_length:
322 case op_check_has_instance:
323 case op_instanceof:
324 case op_get_by_val:
325 case op_typeof:
326 case op_is_undefined:
327 case op_is_boolean:
328 case op_is_number:
329 case op_is_string:
330 case op_is_object:
331 case op_is_object_or_null:
332 case op_is_function:
333 case op_in:
334 case op_to_number:
335 case op_to_string:
336 case op_negate:
337 case op_add:
338 case op_mul:
339 case op_div:
340 case op_mod:
341 case op_sub:
342 case op_lshift:
343 case op_rshift:
344 case op_urshift:
345 case op_bitand:
346 case op_bitxor:
347 case op_bitor:
348 case op_inc:
349 case op_dec:
350 case op_eq:
351 case op_neq:
352 case op_stricteq:
353 case op_nstricteq:
354 case op_less:
355 case op_lesseq:
356 case op_greater:
357 case op_greatereq:
358 case op_neq_null:
359 case op_eq_null:
360 case op_not:
361 case op_mov:
362 case op_new_object:
363 case op_to_this:
364 case op_check_tdz:
365 case op_get_scope:
366 case op_create_direct_arguments:
367 case op_create_scoped_arguments:
368 case op_create_out_of_band_arguments:
369 case op_del_by_id:
370 case op_del_by_val:
371 case op_unsigned:
372 case op_get_from_arguments: {
373 functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
374 return;
375 }
376 case op_catch:
377 case op_create_lexical_environment: {
378 functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
379 functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
380 return;
381 }
382 case op_enter: {
383 for (unsigned i = codeBlock->m_numVars; i--;)
384 functor(codeBlock, instruction, opcodeID, virtualRegisterForLocal(i).offset());
385 return;
386 } }
387 }
388
389 } // namespace JSC
390
391 #endif // BytecodeUseDef_h
392