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