7236b587112d9ec80d9085427a0e6c451e0c4452
[WebKit-https.git] / Source / JavaScriptCore / bytecode / BytecodeUseDef.h
1 /*
2  * Copyright (C) 2013, 2015-2016 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, BytecodeBasicBlock* block, 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_cloned_arguments:
56     case op_get_rest_length:
57     case op_watchdog:
58     case op_log_shadow_chicken_prologue:
59     case op_log_shadow_chicken_tail:
60         return;
61     case op_assert:
62     case op_get_scope:
63     case op_to_this:
64     case op_check_tdz:
65     case op_profile_will_call:
66     case op_profile_did_call:
67     case op_profile_type:
68     case op_throw:
69     case op_end:
70     case op_ret:
71     case op_jtrue:
72     case op_jfalse:
73     case op_jeq_null:
74     case op_jneq_null:
75     case op_dec:
76     case op_inc:
77     case op_resume: {
78         ASSERT(opcodeLengths[opcodeID] > 1);
79         functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
80         return;
81     }
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     case op_set_function_name:
91     case op_copy_rest: {
92         ASSERT(opcodeLengths[opcodeID] > 2);
93         functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
94         functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
95         return;
96     }
97     case op_put_by_val_direct:
98     case op_put_by_val: {
99         ASSERT(opcodeLengths[opcodeID] > 3);
100         functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
101         functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
102         functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
103         return;
104     }
105     case op_put_by_index:
106     case op_put_by_id:
107     case op_put_to_scope:
108     case op_put_to_arguments: {
109         ASSERT(opcodeLengths[opcodeID] > 3);
110         functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
111         functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
112         return;
113     }
114     case op_put_getter_by_id:
115     case op_put_setter_by_id: {
116         ASSERT(opcodeLengths[opcodeID] > 4);
117         functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
118         functor(codeBlock, instruction, opcodeID, instruction[4].u.operand);
119         return;
120     }
121     case op_put_getter_setter_by_id: {
122         ASSERT(opcodeLengths[opcodeID] > 5);
123         functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
124         functor(codeBlock, instruction, opcodeID, instruction[4].u.operand);
125         functor(codeBlock, instruction, opcodeID, instruction[5].u.operand);
126         return;
127     }
128     case op_put_getter_by_val:
129     case op_put_setter_by_val: {
130         ASSERT(opcodeLengths[opcodeID] > 4);
131         functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
132         functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
133         functor(codeBlock, instruction, opcodeID, instruction[4].u.operand);
134         return;
135     }
136     case op_get_property_enumerator:
137     case op_get_enumerable_length:
138     case op_new_func_exp:
139     case op_new_generator_func_exp:
140     case op_new_arrow_func_exp:
141     case op_to_index_string:
142     case op_create_lexical_environment:
143     case op_resolve_scope:
144     case op_get_from_scope:
145     case op_to_primitive:
146     case op_get_by_id:
147     case op_get_array_length:
148     case op_typeof:
149     case op_is_undefined:
150     case op_is_boolean:
151     case op_is_number:
152     case op_is_string:
153     case op_is_object:
154     case op_is_object_or_null:
155     case op_is_function:
156     case op_to_number:
157     case op_to_string:
158     case op_negate:
159     case op_neq_null:
160     case op_eq_null:
161     case op_not:
162     case op_mov:
163     case op_new_array_with_size:
164     case op_create_this:
165     case op_del_by_id:
166     case op_unsigned:
167     case op_new_func:
168     case op_new_generator_func:
169     case op_get_parent_scope:
170     case op_create_scoped_arguments:
171     case op_get_from_arguments: {
172         ASSERT(opcodeLengths[opcodeID] > 2);
173         functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
174         return;
175     }
176     case op_has_generic_property:
177     case op_has_indexed_property:
178     case op_enumerator_structure_pname:
179     case op_enumerator_generic_pname:
180     case op_get_by_val:
181     case op_in:
182     case op_overrides_has_instance:
183     case op_instanceof:
184     case op_add:
185     case op_mul:
186     case op_div:
187     case op_mod:
188     case op_sub:
189     case op_lshift:
190     case op_rshift:
191     case op_urshift:
192     case op_bitand:
193     case op_bitxor:
194     case op_bitor:
195     case op_less:
196     case op_lesseq:
197     case op_greater:
198     case op_greatereq:
199     case op_nstricteq:
200     case op_stricteq:
201     case op_neq:
202     case op_eq:
203     case op_push_with_scope:
204     case op_del_by_val: {
205         ASSERT(opcodeLengths[opcodeID] > 3);
206         functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
207         functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
208         return;
209     }
210     case op_instanceof_custom:
211     case op_has_structure_property:
212     case op_construct_varargs:
213     case op_call_varargs:
214     case op_tail_call_varargs: {
215         ASSERT(opcodeLengths[opcodeID] > 4);
216         functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
217         functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
218         functor(codeBlock, instruction, opcodeID, instruction[4].u.operand);
219         return;
220     }
221     case op_get_direct_pname: {
222         ASSERT(opcodeLengths[opcodeID] > 5);
223         functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
224         functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
225         functor(codeBlock, instruction, opcodeID, instruction[4].u.operand);
226         functor(codeBlock, instruction, opcodeID, instruction[5].u.operand);
227         return;
228     }
229     case op_switch_string:
230     case op_switch_char:
231     case op_switch_imm: {
232         ASSERT(opcodeLengths[opcodeID] > 3);
233         functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
234         return;
235     }
236     case op_new_array:
237     case op_strcat: {
238         int base = instruction[2].u.operand;
239         int count = instruction[3].u.operand;
240         for (int i = 0; i < count; i++)
241             functor(codeBlock, instruction, opcodeID, base - i);
242         return;
243     }
244     case op_construct:
245     case op_call_eval:
246     case op_call:
247     case op_tail_call: {
248         functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
249         int argCount = instruction[3].u.operand;
250         int registerOffset = -instruction[4].u.operand;
251         int lastArg = registerOffset + CallFrame::thisArgumentOffset();
252         for (int i = 0; i < argCount; i++)
253             functor(codeBlock, instruction, opcodeID, lastArg + i);
254         return;
255     }
256     case op_save: {
257         functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
258         unsigned mergePointBytecodeOffset = bytecodeOffset + instruction[3].u.operand;
259         BytecodeBasicBlock* mergePointBlock = nullptr;
260         for (BytecodeBasicBlock* successor : block->successors()) {
261             if (successor->leaderBytecodeOffset() == mergePointBytecodeOffset) {
262                 mergePointBlock = successor;
263                 break;
264             }
265         }
266         ASSERT(mergePointBlock);
267         mergePointBlock->in().forEachSetBit([&](unsigned local) {
268             functor(codeBlock, instruction, opcodeID, virtualRegisterForLocal(local).offset());
269         });
270         return;
271     }
272     default:
273         RELEASE_ASSERT_NOT_REACHED();
274         break;
275     }
276 }
277
278 template<typename Functor>
279 void computeDefsForBytecodeOffset(CodeBlock* codeBlock, BytecodeBasicBlock* block, unsigned bytecodeOffset, const Functor& functor)
280 {
281     Interpreter* interpreter = codeBlock->vm()->interpreter;
282     Instruction* instructionsBegin = codeBlock->instructions().begin();
283     Instruction* instruction = &instructionsBegin[bytecodeOffset];
284     OpcodeID opcodeID = interpreter->getOpcodeID(instruction->u.opcode);
285     switch (opcodeID) {
286     // These don't define anything.
287     case op_copy_rest:
288     case op_put_to_scope:
289     case op_end:
290     case op_profile_will_call:
291     case op_profile_did_call:
292     case op_throw:
293     case op_throw_static_error:
294     case op_save:
295     case op_assert:
296     case op_debug:
297     case op_ret:
298     case op_jmp:
299     case op_jtrue:
300     case op_jfalse:
301     case op_jeq_null:
302     case op_jneq_null:
303     case op_jneq_ptr:
304     case op_jless:
305     case op_jlesseq:
306     case op_jgreater:
307     case op_jgreatereq:
308     case op_jnless:
309     case op_jnlesseq:
310     case op_jngreater:
311     case op_jngreatereq:
312     case op_loop_hint:
313     case op_switch_imm:
314     case op_switch_char:
315     case op_switch_string:
316     case op_put_by_id:
317     case op_put_getter_by_id:
318     case op_put_setter_by_id:
319     case op_put_getter_setter_by_id:
320     case op_put_getter_by_val:
321     case op_put_setter_by_val:
322     case op_put_by_val:
323     case op_put_by_val_direct:
324     case op_put_by_index:
325     case op_profile_type:
326     case op_profile_control_flow:
327     case op_put_to_arguments:
328     case op_set_function_name:
329     case op_watchdog:
330     case op_log_shadow_chicken_prologue:
331     case op_log_shadow_chicken_tail:
332 #define LLINT_HELPER_OPCODES(opcode, length) case opcode:
333         FOR_EACH_LLINT_OPCODE_EXTENSION(LLINT_HELPER_OPCODES);
334 #undef LLINT_HELPER_OPCODES
335         return;
336     // These all have a single destination for the first argument.
337     case op_to_index_string:
338     case op_get_enumerable_length:
339     case op_has_indexed_property:
340     case op_has_structure_property:
341     case op_has_generic_property:
342     case op_get_direct_pname:
343     case op_get_property_enumerator:
344     case op_enumerator_structure_pname:
345     case op_enumerator_generic_pname:
346     case op_get_parent_scope:
347     case op_push_with_scope:
348     case op_create_lexical_environment:
349     case op_resolve_scope:
350     case op_strcat:
351     case op_to_primitive:
352     case op_create_this:
353     case op_new_array:
354     case op_new_array_buffer:
355     case op_new_array_with_size:
356     case op_new_regexp:
357     case op_new_func:
358     case op_new_func_exp:
359     case op_new_generator_func:
360     case op_new_generator_func_exp:
361     case op_new_arrow_func_exp:
362     case op_call_varargs:
363     case op_tail_call_varargs:
364     case op_construct_varargs:
365     case op_get_from_scope:
366     case op_call:
367     case op_tail_call:
368     case op_call_eval:
369     case op_construct:
370     case op_get_by_id:
371     case op_get_array_length:
372     case op_overrides_has_instance:
373     case op_instanceof:
374     case op_instanceof_custom:
375     case op_get_by_val:
376     case op_typeof:
377     case op_is_undefined:
378     case op_is_boolean:
379     case op_is_number:
380     case op_is_string:
381     case op_is_object:
382     case op_is_object_or_null:
383     case op_is_function:
384     case op_in:
385     case op_to_number:
386     case op_to_string:
387     case op_negate:
388     case op_add:
389     case op_mul:
390     case op_div:
391     case op_mod:
392     case op_sub:
393     case op_lshift:
394     case op_rshift:
395     case op_urshift:
396     case op_bitand:
397     case op_bitxor:
398     case op_bitor:
399     case op_inc:
400     case op_dec:
401     case op_eq:
402     case op_neq:
403     case op_stricteq:
404     case op_nstricteq:
405     case op_less:
406     case op_lesseq:
407     case op_greater:
408     case op_greatereq:
409     case op_neq_null:
410     case op_eq_null:
411     case op_not:
412     case op_mov:
413     case op_new_object:
414     case op_to_this:
415     case op_check_tdz:
416     case op_get_scope:
417     case op_create_direct_arguments:
418     case op_create_scoped_arguments:
419     case op_create_cloned_arguments:
420     case op_del_by_id:
421     case op_del_by_val:
422     case op_unsigned:
423     case op_get_from_arguments: 
424     case op_get_rest_length: {
425         ASSERT(opcodeLengths[opcodeID] > 1);
426         functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
427         return;
428     }
429     case op_catch: {
430         ASSERT(opcodeLengths[opcodeID] > 2);
431         functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
432         functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
433         return;
434     }
435     case op_enter: {
436         for (unsigned i = codeBlock->m_numVars; i--;)
437             functor(codeBlock, instruction, opcodeID, virtualRegisterForLocal(i).offset());
438         return;
439     }
440     case op_resume: {
441         RELEASE_ASSERT(block->successors().size() == 1);
442         block->successors()[0]->in().forEachSetBit([&](unsigned local) {
443             functor(codeBlock, instruction, opcodeID, virtualRegisterForLocal(local).offset());
444         });
445         return;
446     }
447     }
448 }
449
450 } // namespace JSC
451
452 #endif // BytecodeUseDef_h
453