1/*
2 * Copyright (C) 2013-2019 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#pragma once
27
28#include "BytecodeStructs.h"
29#include "CodeBlock.h"
30#include "Instruction.h"
31#include <wtf/Forward.h>
32
33namespace JSC {
34
35#define CALL_FUNCTOR(__arg) \
36 functor(__bytecode.m_##__arg);
37
38#define USES_OR_DEFS(__opcode, ...) \
39 case __opcode::opcodeID: { \
40 auto __bytecode = instruction->as<__opcode>(); \
41 WTF_LAZY_FOR_EACH_TERM(CALL_FUNCTOR, __VA_ARGS__) \
42 return; \
43 }
44
45#define USES USES_OR_DEFS
46#define DEFS USES_OR_DEFS
47
48template<typename Block, typename Functor>
49void computeUsesForBytecodeOffset(Block* codeBlock, OpcodeID opcodeID, const Instruction* instruction, const Functor& functor)
50{
51 if (opcodeID != op_enter && (codeBlock->wasCompiledWithDebuggingOpcodes() || codeBlock->usesEval()) && codeBlock->scopeRegister().isValid())
52 functor(codeBlock->scopeRegister());
53
54 auto handleNewArrayLike = [&](auto op) {
55 int base = op.m_argv.offset();
56 for (int i = 0; i < static_cast<int>(op.m_argc); i++)
57 functor(VirtualRegister { base - i });
58 };
59
60 auto handleOpCallLike = [&](auto op) {
61 functor(op.m_callee);
62 int lastArg = -static_cast<int>(op.m_argv) + CallFrame::thisArgumentOffset();
63 for (int i = 0; i < static_cast<int>(op.m_argc); i++)
64 functor(VirtualRegister { lastArg + i });
65 if (opcodeID == op_call_eval)
66 functor(codeBlock->scopeRegister());
67 return;
68 };
69
70 switch (opcodeID) {
71 case op_wide16:
72 case op_wide32:
73 RELEASE_ASSERT_NOT_REACHED();
74
75 // No uses.
76 case op_new_regexp:
77 case op_debug:
78 case op_jneq_ptr:
79 case op_loop_hint:
80 case op_jmp:
81 case op_new_object:
82 case op_enter:
83 case op_argument_count:
84 case op_catch:
85 case op_profile_control_flow:
86 case op_create_direct_arguments:
87 case op_create_cloned_arguments:
88 case op_get_rest_length:
89 case op_check_traps:
90 case op_get_argument:
91 case op_nop:
92 case op_unreachable:
93 case op_super_sampler_begin:
94 case op_super_sampler_end:
95 return;
96
97 USES(OpGetScope, dst)
98 USES(OpToThis, srcDst)
99 USES(OpCheckTdz, targetVirtualRegister)
100 USES(OpIdentityWithProfile, srcDst)
101 USES(OpProfileType, targetVirtualRegister);
102 USES(OpThrow, value)
103 USES(OpThrowStaticError, message)
104 USES(OpEnd, value)
105 USES(OpRet, value)
106 USES(OpJtrue, condition)
107 USES(OpJfalse, condition)
108 USES(OpJeqNull, value)
109 USES(OpJneqNull, value)
110 USES(OpDec, srcDst)
111 USES(OpInc, srcDst)
112 USES(OpLogShadowChickenPrologue, scope)
113
114 USES(OpJless, lhs, rhs)
115 USES(OpJlesseq, lhs, rhs)
116 USES(OpJgreater, lhs, rhs)
117 USES(OpJgreatereq, lhs, rhs)
118 USES(OpJnless, lhs, rhs)
119 USES(OpJnlesseq, lhs, rhs)
120 USES(OpJngreater, lhs, rhs)
121 USES(OpJngreatereq, lhs, rhs)
122 USES(OpJeq, lhs, rhs)
123 USES(OpJneq, lhs, rhs)
124 USES(OpJstricteq, lhs, rhs)
125 USES(OpJnstricteq, lhs, rhs)
126 USES(OpJbelow, lhs, rhs)
127 USES(OpJbeloweq, lhs, rhs)
128 USES(OpSetFunctionName, function, name)
129 USES(OpLogShadowChickenTail, thisValue, scope)
130
131 USES(OpPutByVal, base, property, value)
132 USES(OpPutByValDirect, base, property, value)
133
134 USES(OpPutById, base, value)
135 USES(OpPutToScope, scope, value)
136 USES(OpPutToArguments, arguments, value)
137
138 USES(OpPutByIdWithThis, base, thisValue, value)
139
140 USES(OpPutByValWithThis, base, thisValue, property, value)
141
142 USES(OpPutGetterById, base, accessor)
143 USES(OpPutSetterById, base, accessor)
144
145 USES(OpPutGetterSetterById, base, getter, setter)
146
147 USES(OpPutGetterByVal, base, property, accessor)
148 USES(OpPutSetterByVal, base, property, accessor)
149
150 USES(OpDefineDataProperty, base, property, value, attributes)
151
152 USES(OpDefineAccessorProperty, base, property, getter, setter, attributes)
153
154 USES(OpSpread, argument)
155 USES(OpGetPropertyEnumerator, base)
156 USES(OpGetEnumerableLength, base)
157 USES(OpNewFuncExp, scope)
158 USES(OpNewGeneratorFuncExp, scope)
159 USES(OpNewAsyncFuncExp, scope)
160 USES(OpToIndexString, index)
161 USES(OpCreateLexicalEnvironment, scope, symbolTable, initialValue)
162 USES(OpCreateGeneratorFrameEnvironment, scope, symbolTable, initialValue)
163 USES(OpResolveScope, scope)
164 USES(OpResolveScopeForHoistingFuncDeclInEval, scope)
165 USES(OpGetFromScope, scope)
166 USES(OpToPrimitive, src)
167 USES(OpTryGetById, base)
168 USES(OpGetById, base)
169 USES(OpGetByIdDirect, base)
170 USES(OpInById, base)
171 USES(OpTypeof, value)
172 USES(OpIsEmpty, operand)
173 USES(OpIsUndefined, operand)
174 USES(OpIsUndefinedOrNull, operand)
175 USES(OpIsBoolean, operand)
176 USES(OpIsNumber, operand)
177 USES(OpIsObject, operand)
178 USES(OpIsObjectOrNull, operand)
179 USES(OpIsCellWithType, operand)
180 USES(OpIsFunction, operand)
181 USES(OpToNumber, operand)
182 USES(OpToString, operand)
183 USES(OpToObject, operand)
184 USES(OpNegate, operand)
185 USES(OpBitnot, operand)
186 USES(OpEqNull, operand)
187 USES(OpNeqNull, operand)
188 USES(OpNot, operand)
189 USES(OpUnsigned, operand)
190 USES(OpMov, src)
191 USES(OpNewArrayWithSize, length)
192 USES(OpCreateThis, callee)
193 USES(OpDelById, base)
194 USES(OpNewFunc, scope)
195 USES(OpNewAsyncGeneratorFunc, scope)
196 USES(OpNewAsyncGeneratorFuncExp, scope)
197 USES(OpNewGeneratorFunc, scope)
198 USES(OpNewAsyncFunc, scope)
199 USES(OpGetParentScope, scope)
200 USES(OpCreateScopedArguments, scope)
201 USES(OpCreateRest, arraySize)
202 USES(OpGetFromArguments, arguments)
203 USES(OpNewArrayBuffer, immutableButterfly)
204
205 USES(OpHasGenericProperty, base, property)
206 USES(OpHasIndexedProperty, base, property)
207 USES(OpEnumeratorStructurePname, enumerator, index)
208 USES(OpEnumeratorGenericPname, enumerator, index)
209 USES(OpGetByVal, base, property)
210 USES(OpInByVal, base, property)
211 USES(OpOverridesHasInstance, constructor, hasInstanceValue)
212 USES(OpInstanceof, value, prototype)
213 USES(OpAdd, lhs, rhs)
214 USES(OpMul, lhs, rhs)
215 USES(OpDiv, lhs, rhs)
216 USES(OpMod, lhs, rhs)
217 USES(OpSub, lhs, rhs)
218 USES(OpPow, lhs, rhs)
219 USES(OpLshift, lhs, rhs)
220 USES(OpRshift, lhs, rhs)
221 USES(OpUrshift, lhs, rhs)
222 USES(OpBitand, lhs, rhs)
223 USES(OpBitxor, lhs, rhs)
224 USES(OpBitor, lhs, rhs)
225 USES(OpLess, lhs, rhs)
226 USES(OpLesseq, lhs, rhs)
227 USES(OpGreater, lhs, rhs)
228 USES(OpGreatereq, lhs, rhs)
229 USES(OpBelow, lhs, rhs)
230 USES(OpBeloweq, lhs, rhs)
231 USES(OpNstricteq, lhs, rhs)
232 USES(OpStricteq, lhs, rhs)
233 USES(OpNeq, lhs, rhs)
234 USES(OpEq, lhs, rhs)
235 USES(OpPushWithScope, currentScope, newScope)
236 USES(OpGetByIdWithThis, base, thisValue)
237 USES(OpDelByVal, base, property)
238 USES(OpTailCallForwardArguments, callee, thisValue)
239
240 USES(OpGetByValWithThis, base, thisValue, property)
241 USES(OpInstanceofCustom, value, constructor, hasInstanceValue)
242 USES(OpHasStructureProperty, base, property, enumerator)
243 USES(OpConstructVarargs, callee, thisValue, arguments)
244 USES(OpCallVarargs, callee, thisValue, arguments)
245 USES(OpTailCallVarargs, callee, thisValue, arguments)
246
247 USES(OpGetDirectPname, base, property, index, enumerator)
248
249 USES(OpSwitchString, scrutinee)
250 USES(OpSwitchChar, scrutinee)
251 USES(OpSwitchImm, scrutinee)
252
253 USES(OpYield, generator, argument)
254
255 case op_new_array_with_spread:
256 handleNewArrayLike(instruction->as<OpNewArrayWithSpread>());
257 return;
258 case op_new_array:
259 handleNewArrayLike(instruction->as<OpNewArray>());
260 return;
261
262 case op_strcat: {
263 auto bytecode = instruction->as<OpStrcat>();
264 int base = bytecode.m_src.offset();
265 for (int i = 0; i < bytecode.m_count; i++)
266 functor(VirtualRegister { base - i });
267 return;
268 }
269
270 case op_construct:
271 handleOpCallLike(instruction->as<OpConstruct>());
272 return;
273 case op_call_eval:
274 handleOpCallLike(instruction->as<OpCallEval>());
275 return;
276 case op_call:
277 handleOpCallLike(instruction->as<OpCall>());
278 return;
279 case op_tail_call:
280 handleOpCallLike(instruction->as<OpTailCall>());
281 return;
282
283 default:
284 RELEASE_ASSERT_NOT_REACHED();
285 break;
286 }
287}
288
289template<typename Block, typename Functor>
290void computeDefsForBytecodeOffset(Block* codeBlock, OpcodeID opcodeID, const Instruction* instruction, const Functor& functor)
291{
292 switch (opcodeID) {
293 case op_wide16:
294 case op_wide32:
295 RELEASE_ASSERT_NOT_REACHED();
296
297 // These don't define anything.
298 case op_put_to_scope:
299 case op_end:
300 case op_throw:
301 case op_throw_static_error:
302 case op_check_tdz:
303 case op_debug:
304 case op_ret:
305 case op_jmp:
306 case op_jtrue:
307 case op_jfalse:
308 case op_jeq_null:
309 case op_jneq_null:
310 case op_jneq_ptr:
311 case op_jless:
312 case op_jlesseq:
313 case op_jgreater:
314 case op_jgreatereq:
315 case op_jnless:
316 case op_jnlesseq:
317 case op_jngreater:
318 case op_jngreatereq:
319 case op_jeq:
320 case op_jneq:
321 case op_jstricteq:
322 case op_jnstricteq:
323 case op_jbelow:
324 case op_jbeloweq:
325 case op_loop_hint:
326 case op_switch_imm:
327 case op_switch_char:
328 case op_switch_string:
329 case op_put_by_id:
330 case op_put_by_id_with_this:
331 case op_put_by_val_with_this:
332 case op_put_getter_by_id:
333 case op_put_setter_by_id:
334 case op_put_getter_setter_by_id:
335 case op_put_getter_by_val:
336 case op_put_setter_by_val:
337 case op_put_by_val:
338 case op_put_by_val_direct:
339 case op_define_data_property:
340 case op_define_accessor_property:
341 case op_profile_type:
342 case op_profile_control_flow:
343 case op_put_to_arguments:
344 case op_set_function_name:
345 case op_check_traps:
346 case op_log_shadow_chicken_prologue:
347 case op_log_shadow_chicken_tail:
348 case op_yield:
349 case op_nop:
350 case op_unreachable:
351 case op_super_sampler_begin:
352 case op_super_sampler_end:
353#define LLINT_HELPER_OPCODES(opcode, length) case opcode:
354 FOR_EACH_LLINT_OPCODE_EXTENSION(LLINT_HELPER_OPCODES);
355#undef LLINT_HELPER_OPCODES
356 return;
357 // These all have a single destination for the first argument.
358 DEFS(OpArgumentCount, dst)
359 DEFS(OpToIndexString, dst)
360 DEFS(OpGetEnumerableLength, dst)
361 DEFS(OpHasIndexedProperty, dst)
362 DEFS(OpHasStructureProperty, dst)
363 DEFS(OpHasGenericProperty, dst)
364 DEFS(OpGetDirectPname, dst)
365 DEFS(OpGetPropertyEnumerator, dst)
366 DEFS(OpEnumeratorStructurePname, dst)
367 DEFS(OpEnumeratorGenericPname, dst)
368 DEFS(OpGetParentScope, dst)
369 DEFS(OpPushWithScope, dst)
370 DEFS(OpCreateLexicalEnvironment, dst)
371 DEFS(OpCreateGeneratorFrameEnvironment, dst)
372 DEFS(OpResolveScope, dst)
373 DEFS(OpResolveScopeForHoistingFuncDeclInEval, dst)
374 DEFS(OpStrcat, dst)
375 DEFS(OpToPrimitive, dst)
376 DEFS(OpCreateThis, dst)
377 DEFS(OpNewArray, dst)
378 DEFS(OpNewArrayWithSpread, dst)
379 DEFS(OpSpread, dst)
380 DEFS(OpNewArrayBuffer, dst)
381 DEFS(OpNewArrayWithSize, dst)
382 DEFS(OpNewRegexp, dst)
383 DEFS(OpNewFunc, dst)
384 DEFS(OpNewFuncExp, dst)
385 DEFS(OpNewGeneratorFunc, dst)
386 DEFS(OpNewGeneratorFuncExp, dst)
387 DEFS(OpNewAsyncGeneratorFunc, dst)
388 DEFS(OpNewAsyncGeneratorFuncExp, dst)
389 DEFS(OpNewAsyncFunc, dst)
390 DEFS(OpNewAsyncFuncExp, dst)
391 DEFS(OpCallVarargs, dst)
392 DEFS(OpTailCallVarargs, dst)
393 DEFS(OpTailCallForwardArguments, dst)
394 DEFS(OpConstructVarargs, dst)
395 DEFS(OpGetFromScope, dst)
396 DEFS(OpCall, dst)
397 DEFS(OpTailCall, dst)
398 DEFS(OpCallEval, dst)
399 DEFS(OpConstruct, dst)
400 DEFS(OpTryGetById, dst)
401 DEFS(OpGetById, dst)
402 DEFS(OpGetByIdDirect, dst)
403 DEFS(OpGetByIdWithThis, dst)
404 DEFS(OpGetByValWithThis, dst)
405 DEFS(OpOverridesHasInstance, dst)
406 DEFS(OpInstanceof, dst)
407 DEFS(OpInstanceofCustom, dst)
408 DEFS(OpGetByVal, dst)
409 DEFS(OpTypeof, dst)
410 DEFS(OpIdentityWithProfile, srcDst)
411 DEFS(OpIsEmpty, dst)
412 DEFS(OpIsUndefined, dst)
413 USES(OpIsUndefinedOrNull, dst)
414 DEFS(OpIsBoolean, dst)
415 DEFS(OpIsNumber, dst)
416 DEFS(OpIsObject, dst)
417 DEFS(OpIsObjectOrNull, dst)
418 DEFS(OpIsCellWithType, dst)
419 DEFS(OpIsFunction, dst)
420 DEFS(OpInById, dst)
421 DEFS(OpInByVal, dst)
422 DEFS(OpToNumber, dst)
423 DEFS(OpToString, dst)
424 DEFS(OpToObject, dst)
425 DEFS(OpNegate, dst)
426 DEFS(OpAdd, dst)
427 DEFS(OpMul, dst)
428 DEFS(OpDiv, dst)
429 DEFS(OpMod, dst)
430 DEFS(OpSub, dst)
431 DEFS(OpPow, dst)
432 DEFS(OpLshift, dst)
433 DEFS(OpRshift, dst)
434 DEFS(OpUrshift, dst)
435 DEFS(OpBitand, dst)
436 DEFS(OpBitxor, dst)
437 DEFS(OpBitor, dst)
438 DEFS(OpBitnot, dst)
439 DEFS(OpInc, srcDst)
440 DEFS(OpDec, srcDst)
441 DEFS(OpEq, dst)
442 DEFS(OpNeq, dst)
443 DEFS(OpStricteq, dst)
444 DEFS(OpNstricteq, dst)
445 DEFS(OpLess, dst)
446 DEFS(OpLesseq, dst)
447 DEFS(OpGreater, dst)
448 DEFS(OpGreatereq, dst)
449 DEFS(OpBelow, dst)
450 DEFS(OpBeloweq, dst)
451 DEFS(OpNeqNull, dst)
452 DEFS(OpEqNull, dst)
453 DEFS(OpNot, dst)
454 DEFS(OpMov, dst)
455 DEFS(OpNewObject, dst)
456 DEFS(OpToThis, srcDst)
457 DEFS(OpGetScope, dst)
458 DEFS(OpCreateDirectArguments, dst)
459 DEFS(OpCreateScopedArguments, dst)
460 DEFS(OpCreateClonedArguments, dst)
461 DEFS(OpDelById, dst)
462 DEFS(OpDelByVal, dst)
463 DEFS(OpUnsigned, dst)
464 DEFS(OpGetFromArguments, dst)
465 DEFS(OpGetArgument, dst)
466 DEFS(OpCreateRest, dst)
467 DEFS(OpGetRestLength, dst)
468
469 DEFS(OpCatch, exception, thrownValue)
470
471 case op_enter: {
472 for (unsigned i = codeBlock->numVars(); i--;)
473 functor(virtualRegisterForLocal(i));
474 return;
475 }
476 }
477}
478
479#undef CALL_FUNCTOR
480#undef USES_OR_DEFS
481#undef USES
482#undef DEFS
483} // namespace JSC
484