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