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