1/*
2 * Copyright (C) 2013 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
31namespace JSC {
32
33template<typename Functor>
34void computeUsesForBytecodeOffset(
35    CodeBlock* codeBlock, unsigned bytecodeOffset, 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_resolve_scope:
48    case op_pop_scope:
49    case op_jneq_ptr:
50    case op_new_func_exp:
51    case op_loop_hint:
52    case op_jmp:
53    case op_new_object:
54    case op_init_lazy_reg:
55    case op_get_callee:
56    case op_enter:
57    case op_catch:
58    case op_touch_entry:
59        return;
60    case op_new_func:
61    case op_new_captured_func:
62    case op_create_activation:
63    case op_create_arguments:
64    case op_to_this:
65    case op_tear_off_activation:
66    case op_profile_will_call:
67    case op_profile_did_call:
68    case op_throw:
69    case op_push_with_scope:
70    case op_end:
71    case op_ret:
72    case op_jtrue:
73    case op_jfalse:
74    case op_jeq_null:
75    case op_jneq_null:
76    case op_dec:
77    case op_inc: {
78        functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
79        return;
80    }
81    case op_ret_object_or_this:
82    case op_jlesseq:
83    case op_jgreater:
84    case op_jgreatereq:
85    case op_jnless:
86    case op_jnlesseq:
87    case op_jngreater:
88    case op_jngreatereq:
89    case op_jless: {
90        functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
91        functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
92        return;
93    }
94    case op_put_by_val_direct:
95    case op_put_by_val: {
96        functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
97        functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
98        functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
99        return;
100    }
101    case op_put_by_index:
102    case op_put_by_id_transition_direct:
103    case op_put_by_id_transition_direct_out_of_line:
104    case op_put_by_id_transition_normal:
105    case op_put_by_id_transition_normal_out_of_line:
106    case op_put_by_id_out_of_line:
107    case op_put_by_id:
108    case op_put_to_scope: {
109        functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
110        functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
111        return;
112    }
113    case op_put_getter_setter: {
114        functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
115        functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
116        functor(codeBlock, instruction, opcodeID, instruction[4].u.operand);
117        return;
118    }
119    case op_init_global_const_nop:
120    case op_init_global_const:
121    case op_push_name_scope:
122    case op_get_from_scope:
123    case op_to_primitive:
124    case op_get_by_id:
125    case op_get_by_id_out_of_line:
126    case op_get_array_length:
127    case op_get_arguments_length:
128    case op_typeof:
129    case op_is_undefined:
130    case op_is_boolean:
131    case op_is_number:
132    case op_is_string:
133    case op_is_object:
134    case op_is_function:
135    case op_to_number:
136    case op_negate:
137    case op_neq_null:
138    case op_eq_null:
139    case op_not:
140    case op_mov:
141    case op_captured_mov:
142    case op_new_array_with_size:
143    case op_create_this:
144    case op_get_pnames:
145    case op_del_by_id:
146    case op_unsigned: {
147        functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
148        return;
149    }
150    case op_get_by_val:
151    case op_get_argument_by_val:
152    case op_in:
153    case op_instanceof:
154    case op_check_has_instance:
155    case op_add:
156    case op_mul:
157    case op_div:
158    case op_mod:
159    case op_sub:
160    case op_lshift:
161    case op_rshift:
162    case op_urshift:
163    case op_bitand:
164    case op_bitxor:
165    case op_bitor:
166    case op_less:
167    case op_lesseq:
168    case op_greater:
169    case op_greatereq:
170    case op_nstricteq:
171    case op_stricteq:
172    case op_neq:
173    case op_eq:
174    case op_del_by_val: {
175        functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
176        functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
177        return;
178    }
179    case op_construct_varargs:
180    case op_call_varargs: {
181        functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
182        functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
183        functor(codeBlock, instruction, opcodeID, instruction[4].u.operand);
184        return;
185    }
186    case op_next_pname: {
187        functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
188        functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
189        functor(codeBlock, instruction, opcodeID, instruction[4].u.operand);
190        functor(codeBlock, instruction, opcodeID, instruction[5].u.operand);
191        return;
192    }
193    case op_get_by_pname: {
194        functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
195        functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
196        functor(codeBlock, instruction, opcodeID, instruction[4].u.operand);
197        functor(codeBlock, instruction, opcodeID, instruction[5].u.operand);
198        functor(codeBlock, instruction, opcodeID, instruction[6].u.operand);
199        return;
200    }
201    case op_switch_string:
202    case op_switch_char:
203    case op_switch_imm: {
204        functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
205        return;
206    }
207    case op_new_array:
208    case op_strcat: {
209        int base = instruction[2].u.operand;
210        int count = instruction[3].u.operand;
211        for (int i = 0; i < count; i++)
212            functor(codeBlock, instruction, opcodeID, base - i);
213        return;
214    }
215    case op_construct:
216    case op_call_eval:
217    case op_call: {
218        functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
219        int argCount = instruction[3].u.operand;
220        int registerOffset = -instruction[4].u.operand;
221        int lastArg = registerOffset + CallFrame::thisArgumentOffset();
222        for (int i = opcodeID == op_construct ? 1 : 0; i < argCount; i++)
223            functor(codeBlock, instruction, opcodeID, lastArg + i);
224        return;
225    }
226    case op_tear_off_arguments: {
227        functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
228        functor(codeBlock, instruction, opcodeID, unmodifiedArgumentsRegister(VirtualRegister(instruction[1].u.operand)).offset());
229        functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
230        return;
231    }
232    default:
233        RELEASE_ASSERT_NOT_REACHED();
234        break;
235    }
236}
237
238template<typename Functor>
239void computeDefsForBytecodeOffset(CodeBlock* codeBlock, unsigned bytecodeOffset, Functor& functor)
240{
241    Interpreter* interpreter = codeBlock->vm()->interpreter;
242    Instruction* instructionsBegin = codeBlock->instructions().begin();
243    Instruction* instruction = &instructionsBegin[bytecodeOffset];
244    OpcodeID opcodeID = interpreter->getOpcodeID(instruction->u.opcode);
245    switch (opcodeID) {
246    // These don't define anything.
247    case op_init_global_const:
248    case op_init_global_const_nop:
249    case op_push_name_scope:
250    case op_push_with_scope:
251    case op_put_to_scope:
252    case op_pop_scope:
253    case op_end:
254    case op_profile_will_call:
255    case op_profile_did_call:
256    case op_throw:
257    case op_throw_static_error:
258    case op_debug:
259    case op_ret:
260    case op_ret_object_or_this:
261    case op_jmp:
262    case op_jtrue:
263    case op_jfalse:
264    case op_jeq_null:
265    case op_jneq_null:
266    case op_jneq_ptr:
267    case op_jless:
268    case op_jlesseq:
269    case op_jgreater:
270    case op_jgreatereq:
271    case op_jnless:
272    case op_jnlesseq:
273    case op_jngreater:
274    case op_jngreatereq:
275    case op_loop_hint:
276    case op_switch_imm:
277    case op_switch_char:
278    case op_switch_string:
279    case op_put_by_id:
280    case op_put_by_id_out_of_line:
281    case op_put_by_id_transition_direct:
282    case op_put_by_id_transition_direct_out_of_line:
283    case op_put_by_id_transition_normal:
284    case op_put_by_id_transition_normal_out_of_line:
285    case op_put_getter_setter:
286    case op_put_by_val:
287    case op_put_by_val_direct:
288    case op_put_by_index:
289    case op_tear_off_arguments:
290    case op_touch_entry:
291#define LLINT_HELPER_OPCODES(opcode, length) case opcode:
292        FOR_EACH_LLINT_OPCODE_EXTENSION(LLINT_HELPER_OPCODES);
293#undef LLINT_HELPER_OPCODES
294        return;
295    // These all have a single destination for the first argument.
296    case op_next_pname:
297    case op_resolve_scope:
298    case op_strcat:
299    case op_tear_off_activation:
300    case op_to_primitive:
301    case op_catch:
302    case op_create_this:
303    case op_new_array:
304    case op_new_array_buffer:
305    case op_new_array_with_size:
306    case op_new_regexp:
307    case op_new_func:
308    case op_new_captured_func:
309    case op_new_func_exp:
310    case op_call_varargs:
311    case op_construct_varargs:
312    case op_get_from_scope:
313    case op_call:
314    case op_call_eval:
315    case op_construct:
316    case op_get_by_id:
317    case op_get_by_id_out_of_line:
318    case op_get_array_length:
319    case op_check_has_instance:
320    case op_instanceof:
321    case op_get_by_val:
322    case op_get_argument_by_val:
323    case op_get_by_pname:
324    case op_get_arguments_length:
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_function:
332    case op_in:
333    case op_to_number:
334    case op_negate:
335    case op_add:
336    case op_mul:
337    case op_div:
338    case op_mod:
339    case op_sub:
340    case op_lshift:
341    case op_rshift:
342    case op_urshift:
343    case op_bitand:
344    case op_bitxor:
345    case op_bitor:
346    case op_inc:
347    case op_dec:
348    case op_eq:
349    case op_neq:
350    case op_stricteq:
351    case op_nstricteq:
352    case op_less:
353    case op_lesseq:
354    case op_greater:
355    case op_greatereq:
356    case op_neq_null:
357    case op_eq_null:
358    case op_not:
359    case op_mov:
360    case op_captured_mov:
361    case op_new_object:
362    case op_to_this:
363    case op_get_callee:
364    case op_init_lazy_reg:
365    case op_create_activation:
366    case op_create_arguments:
367    case op_del_by_id:
368    case op_del_by_val:
369    case op_unsigned: {
370        functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
371        return;
372    }
373    case op_get_pnames: {
374        functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
375        functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
376        functor(codeBlock, instruction, opcodeID, instruction[4].u.operand);
377        return;
378    }
379    case op_enter: {
380        for (unsigned i = codeBlock->m_numVars; i--;)
381            functor(codeBlock, instruction, opcodeID, virtualRegisterForLocal(i).offset());
382        return;
383    } }
384}
385
386} // namespace JSC
387
388#endif // BytecodeUseDef_h
389
390