1/*
2 * Copyright (C) 2013-2018 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. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#pragma once
27
28#if ENABLE(DFG_JIT)
29
30#include "DFGAbstractHeap.h"
31#include "DFGGraph.h"
32#include "DFGHeapLocation.h"
33#include "DFGLazyNode.h"
34#include "DFGPureValue.h"
35#include "DOMJITCallDOMGetterSnippet.h"
36#include "DOMJITSignature.h"
37#include "InlineCallFrame.h"
38#include "JSFixedArray.h"
39#include "JSImmutableButterfly.h"
40
41namespace JSC { namespace DFG {
42
43template<typename ReadFunctor, typename WriteFunctor, typename DefFunctor>
44void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFunctor& write, const DefFunctor& def)
45{
46 // Some notes:
47 //
48 // - The canonical way of clobbering the world is to read world and write
49 // heap. This is because World subsumes Heap and Stack, and Stack can be
50 // read by anyone but only written to by explicit stack writing operations.
51 // Of course, claiming to also write World is not wrong; it'll just
52 // pessimise some important optimizations.
53 //
54 // - We cannot hoist, or sink, anything that has effects. This means that the
55 // easiest way of indicating that something cannot be hoisted is to claim
56 // that it side-effects some miscellaneous thing.
57 //
58 // - We cannot hoist forward-exiting nodes without some additional effort. I
59 // believe that what it comes down to is that forward-exiting generally have
60 // their NodeExitsForward cleared upon hoist, except for forward-exiting
61 // nodes that take bogus state as their input. Those are substantially
62 // harder. We disable it for now. In the future we could enable it by having
63 // versions of those nodes that backward-exit instead, but I'm not convinced
64 // of the soundness.
65 //
66 // - Some nodes lie, and claim that they do not read the JSCell_structureID,
67 // JSCell_typeInfoFlags, etc. These are nodes that use the structure in a way
68 // that does not depend on things that change under structure transitions.
69 //
70 // - It's implicitly understood that OSR exits read the world. This is why we
71 // generally don't move or eliminate stores. Every node can exit, so the
72 // read set does not reflect things that would be read if we exited.
73 // Instead, the read set reflects what the node will have to read if it
74 // *doesn't* exit.
75 //
76 // - Broadly, we don't say that we're reading something if that something is
77 // immutable.
78 //
79 // - This must be sound even prior to type inference. We use this as early as
80 // bytecode parsing to determine at which points in the program it's legal to
81 // OSR exit.
82 //
83 // - If you do read(Stack) or read(World), then make sure that readTop() in
84 // PreciseLocalClobberize is correct.
85
86 // While read() and write() are fairly self-explanatory - they track what sorts of things the
87 // node may read or write - the def() functor is more tricky. It tells you the heap locations
88 // (not just abstract heaps) that are defined by a node. A heap location comprises an abstract
89 // heap, some nodes, and a LocationKind. Briefly, a location defined by a node is a location
90 // whose value can be deduced from looking at the node itself. The locations returned must obey
91 // the following properties:
92 //
93 // - If someone wants to CSE a load from the heap, then a HeapLocation object should be
94 // sufficient to find a single matching node.
95 //
96 // - The abstract heap is the only abstract heap that could be clobbered to invalidate any such
97 // CSE attempt. I.e. if clobberize() reports that on every path between some node and a node
98 // that defines a HeapLocation that it wanted, there were no writes to any abstract heap that
99 // overlap the location's heap, then we have a sound match. Effectively, the semantics of
100 // write() and def() are intertwined such that for them to be sound they must agree on what
101 // is CSEable.
102 //
103 // read(), write(), and def() for heap locations is enough to do GCSE on effectful things. To
104 // keep things simple, this code will also def() pure things. def() must be overloaded to also
105 // accept PureValue. This way, a client of clobberize() can implement GCSE entirely using the
106 // information that clobberize() passes to write() and def(). Other clients of clobberize() can
107 // just ignore def() by using a NoOpClobberize functor.
108
109 // We allow the runtime to perform a stack scan at any time. We don't model which nodes get implemented
110 // by calls into the runtime. For debugging we might replace the implementation of any node with a call
111 // to the runtime, and that call may walk stack. Therefore, each node must read() anything that a stack
112 // scan would read. That's what this does.
113 for (InlineCallFrame* inlineCallFrame = node->origin.semantic.inlineCallFrame(); inlineCallFrame; inlineCallFrame = inlineCallFrame->directCaller.inlineCallFrame()) {
114 if (inlineCallFrame->isClosureCall)
115 read(AbstractHeap(Stack, inlineCallFrame->stackOffset + CallFrameSlot::callee));
116 if (inlineCallFrame->isVarargs())
117 read(AbstractHeap(Stack, inlineCallFrame->stackOffset + CallFrameSlot::argumentCount));
118 }
119
120 // We don't want to specifically account which nodes can read from the scope
121 // when the debugger is enabled. It's helpful to just claim all nodes do.
122 // Specifically, if a node allocates, this may call into the debugger's machinery.
123 // The debugger's machinery is free to take a stack trace and try to read from
124 // a scope which is expected to be flushed to the stack.
125 if (graph.hasDebuggerEnabled()) {
126 ASSERT(!node->origin.semantic.inlineCallFrame());
127 read(AbstractHeap(Stack, graph.m_codeBlock->scopeRegister()));
128 }
129
130 switch (node->op()) {
131 case JSConstant:
132 case DoubleConstant:
133 case Int52Constant:
134 def(PureValue(node, node->constant()));
135 return;
136
137 case Identity:
138 case IdentityWithProfile:
139 case Phantom:
140 case Check:
141 case CheckVarargs:
142 case ExtractOSREntryLocal:
143 case CheckStructureImmediate:
144 return;
145
146 case ExtractCatchLocal:
147 read(AbstractHeap(CatchLocals, node->catchOSREntryIndex()));
148 return;
149
150 case ClearCatchLocals:
151 write(CatchLocals);
152 return;
153
154 case LazyJSConstant:
155 // We should enable CSE of LazyJSConstant. It's a little annoying since LazyJSValue has
156 // more bits than we currently have in PureValue.
157 return;
158
159 case CompareEqPtr:
160 def(PureValue(node, node->cellOperand()->cell()));
161 return;
162
163 case ArithIMul:
164 case ArithMin:
165 case ArithMax:
166 case ArithPow:
167 case GetScope:
168 case SkipScope:
169 case GetGlobalObject:
170 case StringCharCodeAt:
171 case StringCodePointAt:
172 case CompareStrictEq:
173 case SameValue:
174 case IsEmpty:
175 case IsUndefined:
176 case IsUndefinedOrNull:
177 case IsBoolean:
178 case IsNumber:
179 case NumberIsInteger:
180 case IsObject:
181 case IsTypedArrayView:
182 case LogicalNot:
183 case CheckInBounds:
184 case DoubleRep:
185 case ValueRep:
186 case Int52Rep:
187 case BooleanToNumber:
188 case FiatInt52:
189 case MakeRope:
190 case StrCat:
191 case ValueToInt32:
192 case GetExecutable:
193 case BottomValue:
194 case TypeOf:
195 def(PureValue(node));
196 return;
197
198 case GetGlobalThis:
199 read(World);
200 return;
201
202 case AtomicsIsLockFree:
203 if (node->child1().useKind() == Int32Use)
204 def(PureValue(node));
205 else {
206 read(World);
207 write(Heap);
208 }
209 return;
210
211 case ArithUnary:
212 if (node->child1().useKind() == DoubleRepUse)
213 def(PureValue(node, static_cast<std::underlying_type<Arith::UnaryType>::type>(node->arithUnaryType())));
214 else {
215 read(World);
216 write(Heap);
217 }
218 return;
219
220 case ArithFRound:
221 case ArithSqrt:
222 if (node->child1().useKind() == DoubleRepUse)
223 def(PureValue(node));
224 else {
225 read(World);
226 write(Heap);
227 }
228 return;
229
230 case ArithAbs:
231 if (node->child1().useKind() == Int32Use || node->child1().useKind() == DoubleRepUse)
232 def(PureValue(node));
233 else {
234 read(World);
235 write(Heap);
236 }
237 return;
238
239 case ArithClz32:
240 if (node->child1().useKind() == Int32Use || node->child1().useKind() == KnownInt32Use)
241 def(PureValue(node));
242 else {
243 read(World);
244 write(Heap);
245 }
246 return;
247
248 case ArithNegate:
249 if (node->child1().useKind() == Int32Use
250 || node->child1().useKind() == DoubleRepUse
251 || node->child1().useKind() == Int52RepUse)
252 def(PureValue(node));
253 else {
254 read(World);
255 write(Heap);
256 }
257 return;
258
259 case IsCellWithType:
260 def(PureValue(node, node->queriedType()));
261 return;
262
263 case ValueBitNot:
264 if (node->child1().useKind() == BigIntUse) {
265 def(PureValue(node));
266 return;
267 }
268 read(World);
269 write(Heap);
270 return;
271
272 case ArithBitNot:
273 if (node->child1().useKind() == UntypedUse) {
274 read(World);
275 write(Heap);
276 return;
277 }
278 def(PureValue(node));
279 return;
280
281 case ArithBitAnd:
282 case ArithBitOr:
283 case ArithBitXor:
284 case ArithBitLShift:
285 case ArithBitRShift:
286 case BitURShift:
287 if (node->child1().useKind() == UntypedUse || node->child2().useKind() == UntypedUse) {
288 read(World);
289 write(Heap);
290 return;
291 }
292 def(PureValue(node));
293 return;
294
295 case ArithRandom:
296 read(MathDotRandomState);
297 write(MathDotRandomState);
298 return;
299
300 case GetEnumerableLength: {
301 read(Heap);
302 write(SideState);
303 return;
304 }
305
306 case ToIndexString:
307 case GetEnumeratorStructurePname:
308 case GetEnumeratorGenericPname: {
309 def(PureValue(node));
310 return;
311 }
312
313 case HasIndexedProperty: {
314 read(JSObject_butterfly);
315 ArrayMode mode = node->arrayMode();
316 switch (mode.type()) {
317 case Array::ForceExit: {
318 write(SideState);
319 return;
320 }
321 case Array::Int32: {
322 if (mode.isInBounds()) {
323 read(Butterfly_publicLength);
324 read(IndexedInt32Properties);
325 def(HeapLocation(HasIndexedPropertyLoc, IndexedInt32Properties, graph.varArgChild(node, 0), graph.varArgChild(node, 1)), LazyNode(node));
326 return;
327 }
328 read(Heap);
329 return;
330 }
331
332 case Array::Double: {
333 if (mode.isInBounds()) {
334 read(Butterfly_publicLength);
335 read(IndexedDoubleProperties);
336 def(HeapLocation(HasIndexedPropertyLoc, IndexedDoubleProperties, graph.varArgChild(node, 0), graph.varArgChild(node, 1)), LazyNode(node));
337 return;
338 }
339 read(Heap);
340 return;
341 }
342
343 case Array::Contiguous: {
344 if (mode.isInBounds()) {
345 read(Butterfly_publicLength);
346 read(IndexedContiguousProperties);
347 def(HeapLocation(HasIndexedPropertyLoc, IndexedContiguousProperties, graph.varArgChild(node, 0), graph.varArgChild(node, 1)), LazyNode(node));
348 return;
349 }
350 read(Heap);
351 return;
352 }
353
354 case Array::ArrayStorage: {
355 if (mode.isInBounds()) {
356 read(Butterfly_vectorLength);
357 read(IndexedArrayStorageProperties);
358 return;
359 }
360 read(Heap);
361 return;
362 }
363
364 default: {
365 read(World);
366 write(Heap);
367 return;
368 }
369 }
370 RELEASE_ASSERT_NOT_REACHED();
371 return;
372 }
373
374 case StringFromCharCode:
375 switch (node->child1().useKind()) {
376 case Int32Use:
377 def(PureValue(node));
378 return;
379 case UntypedUse:
380 read(World);
381 write(Heap);
382 return;
383 default:
384 DFG_CRASH(graph, node, "Bad use kind");
385 }
386 return;
387
388 case ArithAdd:
389 case ArithMod:
390 case DoubleAsInt32:
391 case UInt32ToNumber:
392 def(PureValue(node, node->arithMode()));
393 return;
394
395 case ArithDiv:
396 case ArithMul:
397 case ArithSub:
398 switch (node->binaryUseKind()) {
399 case Int32Use:
400 case Int52RepUse:
401 case DoubleRepUse:
402 def(PureValue(node, node->arithMode()));
403 return;
404 case UntypedUse:
405 read(World);
406 write(Heap);
407 return;
408 default:
409 DFG_CRASH(graph, node, "Bad use kind");
410 }
411
412 case ArithRound:
413 case ArithFloor:
414 case ArithCeil:
415 case ArithTrunc:
416 if (node->child1().useKind() == DoubleRepUse)
417 def(PureValue(node, static_cast<uintptr_t>(node->arithRoundingMode())));
418 else {
419 read(World);
420 write(Heap);
421 }
422 return;
423
424 case CheckCell:
425 def(PureValue(CheckCell, AdjacencyList(AdjacencyList::Fixed, node->child1()), node->cellOperand()));
426 return;
427
428 case CheckNotEmpty:
429 def(PureValue(CheckNotEmpty, AdjacencyList(AdjacencyList::Fixed, node->child1())));
430 return;
431
432 case AssertNotEmpty:
433 write(SideState);
434 return;
435
436 case CheckIdent:
437 def(PureValue(CheckIdent, AdjacencyList(AdjacencyList::Fixed, node->child1()), node->uidOperand()));
438 return;
439
440 case ConstantStoragePointer:
441 def(PureValue(node, node->storagePointer()));
442 return;
443
444 case KillStack:
445 write(AbstractHeap(Stack, node->unlinkedLocal()));
446 return;
447
448 case MovHint:
449 case ZombieHint:
450 case ExitOK:
451 case Upsilon:
452 case Phi:
453 case PhantomLocal:
454 case SetArgumentDefinitely:
455 case SetArgumentMaybe:
456 case Jump:
457 case Branch:
458 case Switch:
459 case EntrySwitch:
460 case ForceOSRExit:
461 case CPUIntrinsic:
462 case CheckBadCell:
463 case Return:
464 case Unreachable:
465 case CheckTierUpInLoop:
466 case CheckTierUpAtReturn:
467 case CheckTierUpAndOSREnter:
468 case LoopHint:
469 case ProfileType:
470 case ProfileControlFlow:
471 case PutHint:
472 case InitializeEntrypointArguments:
473 case FilterCallLinkStatus:
474 case FilterGetByStatus:
475 case FilterPutByIdStatus:
476 case FilterInByIdStatus:
477 write(SideState);
478 return;
479
480 case StoreBarrier:
481 read(JSCell_cellState);
482 write(JSCell_cellState);
483 return;
484
485 case FencedStoreBarrier:
486 read(Heap);
487 write(JSCell_cellState);
488 return;
489
490 case CheckTraps:
491 read(InternalState);
492 write(InternalState);
493 return;
494
495 case InvalidationPoint:
496 write(SideState);
497 def(HeapLocation(InvalidationPointLoc, Watchpoint_fire), LazyNode(node));
498 return;
499
500 case Flush:
501 read(AbstractHeap(Stack, node->local()));
502 write(SideState);
503 return;
504
505 case NotifyWrite:
506 write(Watchpoint_fire);
507 write(SideState);
508 return;
509
510 case PushWithScope: {
511 read(World);
512 write(HeapObjectCount);
513 return;
514 }
515
516 case CreateActivation: {
517 SymbolTable* table = node->castOperand<SymbolTable*>();
518 if (table->singleton().isStillValid())
519 write(Watchpoint_fire);
520 read(HeapObjectCount);
521 write(HeapObjectCount);
522 return;
523 }
524
525 case CreateDirectArguments:
526 case CreateScopedArguments:
527 case CreateClonedArguments:
528 read(Stack);
529 read(HeapObjectCount);
530 write(HeapObjectCount);
531 return;
532
533 case PhantomDirectArguments:
534 case PhantomClonedArguments:
535 // DFG backend requires that the locals that this reads are flushed. FTL backend can handle those
536 // locals being promoted.
537 if (!graph.m_plan.isFTL())
538 read(Stack);
539
540 // Even though it's phantom, it still has the property that one can't be replaced with another.
541 read(HeapObjectCount);
542 write(HeapObjectCount);
543 return;
544
545 case PhantomSpread:
546 case PhantomNewArrayWithSpread:
547 case PhantomNewArrayBuffer:
548 case PhantomCreateRest:
549 // Even though it's phantom, it still has the property that one can't be replaced with another.
550 read(HeapObjectCount);
551 write(HeapObjectCount);
552 return;
553
554 case CallObjectConstructor:
555 read(HeapObjectCount);
556 write(HeapObjectCount);
557 return;
558
559 case ToThis:
560 read(MiscFields);
561 read(HeapObjectCount);
562 write(HeapObjectCount);
563 return;
564
565 case IsObjectOrNull:
566 read(MiscFields);
567 def(HeapLocation(IsObjectOrNullLoc, MiscFields, node->child1()), LazyNode(node));
568 return;
569
570 case IsFunction:
571 read(MiscFields);
572 def(HeapLocation(IsFunctionLoc, MiscFields, node->child1()), LazyNode(node));
573 return;
574
575 case MatchStructure:
576 read(JSCell_structureID);
577 return;
578
579 case ArraySlice:
580 read(MiscFields);
581 read(JSCell_indexingType);
582 read(JSCell_structureID);
583 read(JSObject_butterfly);
584 read(Butterfly_publicLength);
585 read(IndexedDoubleProperties);
586 read(IndexedInt32Properties);
587 read(IndexedContiguousProperties);
588 read(HeapObjectCount);
589 write(HeapObjectCount);
590 return;
591
592 case ArrayIndexOf: {
593 // FIXME: Should support a CSE rule.
594 // https://bugs.webkit.org/show_bug.cgi?id=173173
595 read(MiscFields);
596 read(JSCell_indexingType);
597 read(JSCell_structureID);
598 read(JSObject_butterfly);
599 read(Butterfly_publicLength);
600 switch (node->arrayMode().type()) {
601 case Array::Double:
602 read(IndexedDoubleProperties);
603 return;
604 case Array::Int32:
605 read(IndexedInt32Properties);
606 return;
607 case Array::Contiguous:
608 read(IndexedContiguousProperties);
609 return;
610 default:
611 RELEASE_ASSERT_NOT_REACHED();
612 return;
613 }
614 return;
615 }
616
617 case GetById:
618 case GetByIdFlush:
619 case GetByIdWithThis:
620 case GetByIdDirect:
621 case GetByIdDirectFlush:
622 case GetByValWithThis:
623 case PutById:
624 case PutByIdWithThis:
625 case PutByValWithThis:
626 case PutByIdFlush:
627 case PutByIdDirect:
628 case PutGetterById:
629 case PutSetterById:
630 case PutGetterSetterById:
631 case PutGetterByVal:
632 case PutSetterByVal:
633 case DefineDataProperty:
634 case DefineAccessorProperty:
635 case DeleteById:
636 case DeleteByVal:
637 case ArrayPush:
638 case ArrayPop:
639 case Call:
640 case DirectCall:
641 case TailCallInlinedCaller:
642 case DirectTailCallInlinedCaller:
643 case Construct:
644 case DirectConstruct:
645 case CallVarargs:
646 case CallForwardVarargs:
647 case TailCallVarargsInlinedCaller:
648 case TailCallForwardVarargsInlinedCaller:
649 case ConstructVarargs:
650 case ConstructForwardVarargs:
651 case ToPrimitive:
652 case InByVal:
653 case InById:
654 case HasOwnProperty:
655 case ValueNegate:
656 case SetFunctionName:
657 case GetDynamicVar:
658 case PutDynamicVar:
659 case ResolveScopeForHoistingFuncDeclInEval:
660 case ResolveScope:
661 case ToObject:
662 case HasGenericProperty:
663 case HasStructureProperty:
664 case GetPropertyEnumerator:
665 case GetDirectPname:
666 case InstanceOfCustom:
667 case ToNumber:
668 case ToNumeric:
669 case NumberToStringWithRadix:
670 case CreateThis:
671 case CreatePromise:
672 case CreateGenerator:
673 case CreateAsyncGenerator:
674 case InstanceOf:
675 case StringValueOf:
676 case ObjectKeys:
677 read(World);
678 write(Heap);
679 return;
680
681 case Inc:
682 case Dec:
683 switch (node->child1().useKind()) {
684 case Int32Use:
685 case Int52RepUse:
686 case DoubleRepUse:
687 case BigIntUse:
688 def(PureValue(node));
689 return;
690 case UntypedUse:
691 read(World);
692 write(Heap);
693 return;
694 default:
695 DFG_CRASH(graph, node, "Bad use kind");
696 }
697
698 case ValueBitAnd:
699 case ValueBitXor:
700 case ValueBitOr:
701 case ValueAdd:
702 case ValueSub:
703 case ValueMul:
704 case ValueDiv:
705 case ValueMod:
706 case ValuePow:
707 case ValueBitLShift:
708 case ValueBitRShift:
709 if (node->isBinaryUseKind(BigIntUse)) {
710 def(PureValue(node));
711 return;
712 }
713 read(World);
714 write(Heap);
715 return;
716
717 case AtomicsAdd:
718 case AtomicsAnd:
719 case AtomicsCompareExchange:
720 case AtomicsExchange:
721 case AtomicsLoad:
722 case AtomicsOr:
723 case AtomicsStore:
724 case AtomicsSub:
725 case AtomicsXor: {
726 unsigned numExtraArgs = numExtraAtomicsArgs(node->op());
727 Edge storageEdge = graph.child(node, 2 + numExtraArgs);
728 if (!storageEdge) {
729 read(World);
730 write(Heap);
731 return;
732 }
733 read(TypedArrayProperties);
734 read(MiscFields);
735 write(TypedArrayProperties);
736 return;
737 }
738
739 case CallEval:
740 ASSERT(!node->origin.semantic.inlineCallFrame());
741 read(AbstractHeap(Stack, graph.m_codeBlock->scopeRegister()));
742 read(AbstractHeap(Stack, virtualRegisterForArgument(0)));
743 read(World);
744 write(Heap);
745 return;
746
747 case Throw:
748 case ThrowStaticError:
749 case TailCall:
750 case DirectTailCall:
751 case TailCallVarargs:
752 case TailCallForwardVarargs:
753 read(World);
754 write(SideState);
755 return;
756
757 case GetGetter:
758 read(GetterSetter_getter);
759 def(HeapLocation(GetterLoc, GetterSetter_getter, node->child1()), LazyNode(node));
760 return;
761
762 case GetSetter:
763 read(GetterSetter_setter);
764 def(HeapLocation(SetterLoc, GetterSetter_setter, node->child1()), LazyNode(node));
765 return;
766
767 case GetCallee:
768 read(AbstractHeap(Stack, CallFrameSlot::callee));
769 def(HeapLocation(StackLoc, AbstractHeap(Stack, CallFrameSlot::callee)), LazyNode(node));
770 return;
771
772 case SetCallee:
773 write(AbstractHeap(Stack, CallFrameSlot::callee));
774 return;
775
776 case GetArgumentCountIncludingThis: {
777 auto heap = AbstractHeap(Stack, remapOperand(node->argumentsInlineCallFrame(), VirtualRegister(CallFrameSlot::argumentCount)));
778 read(heap);
779 def(HeapLocation(StackPayloadLoc, heap), LazyNode(node));
780 return;
781 }
782
783 case SetArgumentCountIncludingThis:
784 write(AbstractHeap(Stack, CallFrameSlot::argumentCount));
785 return;
786
787 case GetRestLength:
788 read(Stack);
789 return;
790
791 case GetLocal:
792 read(AbstractHeap(Stack, node->local()));
793 def(HeapLocation(StackLoc, AbstractHeap(Stack, node->local())), LazyNode(node));
794 return;
795
796 case SetLocal:
797 write(AbstractHeap(Stack, node->local()));
798 def(HeapLocation(StackLoc, AbstractHeap(Stack, node->local())), LazyNode(node->child1().node()));
799 return;
800
801 case GetStack: {
802 AbstractHeap heap(Stack, node->stackAccessData()->local);
803 read(heap);
804 def(HeapLocation(StackLoc, heap), LazyNode(node));
805 return;
806 }
807
808 case PutStack: {
809 AbstractHeap heap(Stack, node->stackAccessData()->local);
810 write(heap);
811 def(HeapLocation(StackLoc, heap), LazyNode(node->child1().node()));
812 return;
813 }
814
815 case LoadVarargs: {
816 read(World);
817 write(Heap);
818 LoadVarargsData* data = node->loadVarargsData();
819 write(AbstractHeap(Stack, data->count.offset()));
820 for (unsigned i = data->limit; i--;)
821 write(AbstractHeap(Stack, data->start.offset() + static_cast<int>(i)));
822 return;
823 }
824
825 case ForwardVarargs: {
826 // We could be way more precise here.
827 read(Stack);
828
829 LoadVarargsData* data = node->loadVarargsData();
830 write(AbstractHeap(Stack, data->count.offset()));
831 for (unsigned i = data->limit; i--;)
832 write(AbstractHeap(Stack, data->start.offset() + static_cast<int>(i)));
833 return;
834 }
835
836 case GetByVal: {
837 ArrayMode mode = node->arrayMode();
838 LocationKind indexedPropertyLoc = indexedPropertyLocForResultType(node->result());
839 switch (mode.type()) {
840 case Array::SelectUsingPredictions:
841 case Array::Unprofiled:
842 case Array::SelectUsingArguments:
843 // Assume the worst since we don't have profiling yet.
844 read(World);
845 write(Heap);
846 return;
847
848 case Array::ForceExit:
849 write(SideState);
850 return;
851
852 case Array::Generic:
853 read(World);
854 write(Heap);
855 return;
856
857 case Array::String:
858 if (mode.isOutOfBounds()) {
859 read(World);
860 write(Heap);
861 return;
862 }
863 // This appears to read nothing because it's only reading immutable data.
864 def(PureValue(graph, node, mode.asWord()));
865 return;
866
867 case Array::DirectArguments:
868 if (mode.isInBounds()) {
869 read(DirectArgumentsProperties);
870 def(HeapLocation(indexedPropertyLoc, DirectArgumentsProperties, graph.varArgChild(node, 0), graph.varArgChild(node, 1)), LazyNode(node));
871 return;
872 }
873 read(World);
874 write(Heap);
875 return;
876
877 case Array::ScopedArguments:
878 read(ScopeProperties);
879 def(HeapLocation(indexedPropertyLoc, ScopeProperties, graph.varArgChild(node, 0), graph.varArgChild(node, 1)), LazyNode(node));
880 return;
881
882 case Array::Int32:
883 if (mode.isInBounds()) {
884 read(Butterfly_publicLength);
885 read(IndexedInt32Properties);
886 def(HeapLocation(indexedPropertyLoc, IndexedInt32Properties, graph.varArgChild(node, 0), graph.varArgChild(node, 1)), LazyNode(node));
887 return;
888 }
889 read(World);
890 write(Heap);
891 return;
892
893 case Array::Double:
894 if (mode.isInBounds()) {
895 read(Butterfly_publicLength);
896 read(IndexedDoubleProperties);
897 LocationKind kind = mode.isSaneChain() ? IndexedPropertyDoubleSaneChainLoc : IndexedPropertyDoubleLoc;
898 def(HeapLocation(kind, IndexedDoubleProperties, graph.varArgChild(node, 0), graph.varArgChild(node, 1)), LazyNode(node));
899 return;
900 }
901 read(World);
902 write(Heap);
903 return;
904
905 case Array::Contiguous:
906 if (mode.isInBounds()) {
907 read(Butterfly_publicLength);
908 read(IndexedContiguousProperties);
909 def(HeapLocation(indexedPropertyLoc, IndexedContiguousProperties, graph.varArgChild(node, 0), graph.varArgChild(node, 1)), LazyNode(node));
910 return;
911 }
912 read(World);
913 write(Heap);
914 return;
915
916 case Array::Undecided:
917 def(PureValue(graph, node));
918 return;
919
920 case Array::ArrayStorage:
921 case Array::SlowPutArrayStorage:
922 if (mode.isInBounds()) {
923 read(Butterfly_vectorLength);
924 read(IndexedArrayStorageProperties);
925 return;
926 }
927 read(World);
928 write(Heap);
929 return;
930
931 case Array::Int8Array:
932 case Array::Int16Array:
933 case Array::Int32Array:
934 case Array::Uint8Array:
935 case Array::Uint8ClampedArray:
936 case Array::Uint16Array:
937 case Array::Uint32Array:
938 case Array::Float32Array:
939 case Array::Float64Array:
940 read(TypedArrayProperties);
941 read(MiscFields);
942 def(HeapLocation(indexedPropertyLoc, TypedArrayProperties, graph.varArgChild(node, 0), graph.varArgChild(node, 1)), LazyNode(node));
943 return;
944 // We should not get an AnyTypedArray in a GetByVal as AnyTypedArray is only created from intrinsics, which
945 // are only added from Inline Caching a GetById.
946 case Array::AnyTypedArray:
947 DFG_CRASH(graph, node, "impossible array mode for get");
948 return;
949 }
950 RELEASE_ASSERT_NOT_REACHED();
951 return;
952 }
953
954 case GetMyArgumentByVal:
955 case GetMyArgumentByValOutOfBounds: {
956 read(Stack);
957 // FIXME: It would be trivial to have a def here.
958 // https://bugs.webkit.org/show_bug.cgi?id=143077
959 return;
960 }
961
962 case PutByValDirect:
963 case PutByVal:
964 case PutByValAlias: {
965 ArrayMode mode = node->arrayMode();
966 Node* base = graph.varArgChild(node, 0).node();
967 Node* index = graph.varArgChild(node, 1).node();
968 Node* value = graph.varArgChild(node, 2).node();
969 LocationKind indexedPropertyLoc = indexedPropertyLocForResultType(node->result());
970
971 switch (mode.modeForPut().type()) {
972 case Array::SelectUsingPredictions:
973 case Array::SelectUsingArguments:
974 case Array::Unprofiled:
975 case Array::Undecided:
976 // Assume the worst since we don't have profiling yet.
977 read(World);
978 write(Heap);
979 return;
980
981 case Array::ForceExit:
982 write(SideState);
983 return;
984
985 case Array::Generic:
986 read(World);
987 write(Heap);
988 return;
989
990 case Array::Int32:
991 if (node->arrayMode().isOutOfBounds()) {
992 read(World);
993 write(Heap);
994 return;
995 }
996 read(Butterfly_publicLength);
997 read(Butterfly_vectorLength);
998 read(IndexedInt32Properties);
999 write(IndexedInt32Properties);
1000 if (node->arrayMode().mayStoreToHole())
1001 write(Butterfly_publicLength);
1002 def(HeapLocation(indexedPropertyLoc, IndexedInt32Properties, base, index), LazyNode(value));
1003 return;
1004
1005 case Array::Double:
1006 if (node->arrayMode().isOutOfBounds()) {
1007 read(World);
1008 write(Heap);
1009 return;
1010 }
1011 read(Butterfly_publicLength);
1012 read(Butterfly_vectorLength);
1013 read(IndexedDoubleProperties);
1014 write(IndexedDoubleProperties);
1015 if (node->arrayMode().mayStoreToHole())
1016 write(Butterfly_publicLength);
1017 def(HeapLocation(IndexedPropertyDoubleLoc, IndexedDoubleProperties, base, index), LazyNode(value));
1018 def(HeapLocation(IndexedPropertyDoubleSaneChainLoc, IndexedDoubleProperties, base, index), LazyNode(value));
1019 return;
1020
1021 case Array::Contiguous:
1022 if (node->arrayMode().isOutOfBounds()) {
1023 read(World);
1024 write(Heap);
1025 return;
1026 }
1027 read(Butterfly_publicLength);
1028 read(Butterfly_vectorLength);
1029 read(IndexedContiguousProperties);
1030 write(IndexedContiguousProperties);
1031 if (node->arrayMode().mayStoreToHole())
1032 write(Butterfly_publicLength);
1033 def(HeapLocation(indexedPropertyLoc, IndexedContiguousProperties, base, index), LazyNode(value));
1034 return;
1035
1036 case Array::ArrayStorage:
1037 if (node->arrayMode().isOutOfBounds()) {
1038 read(World);
1039 write(Heap);
1040 return;
1041 }
1042 read(Butterfly_publicLength);
1043 read(Butterfly_vectorLength);
1044 read(IndexedArrayStorageProperties);
1045 write(IndexedArrayStorageProperties);
1046 if (node->arrayMode().mayStoreToHole())
1047 write(Butterfly_publicLength);
1048 return;
1049
1050 case Array::SlowPutArrayStorage:
1051 if (node->arrayMode().mayStoreToHole()) {
1052 read(World);
1053 write(Heap);
1054 return;
1055 }
1056 read(Butterfly_publicLength);
1057 read(Butterfly_vectorLength);
1058 read(IndexedArrayStorageProperties);
1059 write(IndexedArrayStorageProperties);
1060 return;
1061
1062 case Array::Int8Array:
1063 case Array::Int16Array:
1064 case Array::Int32Array:
1065 case Array::Uint8Array:
1066 case Array::Uint8ClampedArray:
1067 case Array::Uint16Array:
1068 case Array::Uint32Array:
1069 case Array::Float32Array:
1070 case Array::Float64Array:
1071 read(MiscFields);
1072 write(TypedArrayProperties);
1073 // FIXME: We can't def() anything here because these operations truncate their inputs.
1074 // https://bugs.webkit.org/show_bug.cgi?id=134737
1075 return;
1076 case Array::AnyTypedArray:
1077 case Array::String:
1078 case Array::DirectArguments:
1079 case Array::ScopedArguments:
1080 DFG_CRASH(graph, node, "impossible array mode for put");
1081 return;
1082 }
1083 RELEASE_ASSERT_NOT_REACHED();
1084 return;
1085 }
1086
1087 case CheckStructureOrEmpty:
1088 case CheckStructure:
1089 read(JSCell_structureID);
1090 return;
1091
1092 case CheckArray:
1093 read(JSCell_indexingType);
1094 read(JSCell_typeInfoType);
1095 read(JSCell_structureID);
1096 return;
1097
1098 case CheckTypeInfoFlags:
1099 read(JSCell_typeInfoFlags);
1100 def(HeapLocation(CheckTypeInfoFlagsLoc, JSCell_typeInfoFlags, node->child1()), LazyNode(node));
1101 return;
1102
1103 case ParseInt:
1104 // Note: We would have eliminated a ParseInt that has just a single child as an Int32Use inside fixup.
1105 if (node->child1().useKind() == StringUse && (!node->child2() || node->child2().useKind() == Int32Use)) {
1106 def(PureValue(node));
1107 return;
1108 }
1109
1110 read(World);
1111 write(Heap);
1112 return;
1113
1114 case OverridesHasInstance:
1115 read(JSCell_typeInfoFlags);
1116 def(HeapLocation(OverridesHasInstanceLoc, JSCell_typeInfoFlags, node->child1()), LazyNode(node));
1117 return;
1118
1119 case PutStructure:
1120 read(JSObject_butterfly);
1121 write(JSCell_structureID);
1122 write(JSCell_typeInfoType);
1123 write(JSCell_typeInfoFlags);
1124 write(JSCell_indexingType);
1125 return;
1126
1127 case AllocatePropertyStorage:
1128 case ReallocatePropertyStorage:
1129 read(HeapObjectCount);
1130 write(HeapObjectCount);
1131 return;
1132
1133 case NukeStructureAndSetButterfly:
1134 write(JSObject_butterfly);
1135 write(JSCell_structureID);
1136 def(HeapLocation(ButterflyLoc, JSObject_butterfly, node->child1()), LazyNode(node->child2().node()));
1137 return;
1138
1139 case GetButterfly:
1140 read(JSObject_butterfly);
1141 def(HeapLocation(ButterflyLoc, JSObject_butterfly, node->child1()), LazyNode(node));
1142 return;
1143
1144 case CheckSubClass:
1145 def(PureValue(node, node->classInfo()));
1146 return;
1147
1148 case CallDOMGetter: {
1149 DOMJIT::CallDOMGetterSnippet* snippet = node->callDOMGetterData()->snippet;
1150 if (!snippet) {
1151 read(World);
1152 write(Heap);
1153 return;
1154 }
1155 DOMJIT::Effect effect = snippet->effect;
1156 if (effect.reads) {
1157 if (effect.reads == DOMJIT::HeapRange::top())
1158 read(World);
1159 else
1160 read(AbstractHeap(DOMState, effect.reads.rawRepresentation()));
1161 }
1162 if (effect.writes) {
1163 if (effect.writes == DOMJIT::HeapRange::top())
1164 write(Heap);
1165 else
1166 write(AbstractHeap(DOMState, effect.writes.rawRepresentation()));
1167 }
1168 if (effect.def != DOMJIT::HeapRange::top()) {
1169 DOMJIT::HeapRange range = effect.def;
1170 if (range == DOMJIT::HeapRange::none())
1171 def(PureValue(node, bitwise_cast<uintptr_t>(node->callDOMGetterData()->customAccessorGetter)));
1172 else {
1173 // Def with heap location. We do not include "GlobalObject" for that since this information is included in the base node.
1174 // We only see the DOMJIT getter here. So just including "base" is ok.
1175 def(HeapLocation(DOMStateLoc, AbstractHeap(DOMState, range.rawRepresentation()), node->child1()), LazyNode(node));
1176 }
1177 }
1178 return;
1179 }
1180
1181 case CallDOM: {
1182 const DOMJIT::Signature* signature = node->signature();
1183 DOMJIT::Effect effect = signature->effect;
1184 if (effect.reads) {
1185 if (effect.reads == DOMJIT::HeapRange::top())
1186 read(World);
1187 else
1188 read(AbstractHeap(DOMState, effect.reads.rawRepresentation()));
1189 }
1190 if (effect.writes) {
1191 if (effect.writes == DOMJIT::HeapRange::top())
1192 write(Heap);
1193 else
1194 write(AbstractHeap(DOMState, effect.writes.rawRepresentation()));
1195 }
1196 ASSERT_WITH_MESSAGE(effect.def == DOMJIT::HeapRange::top(), "Currently, we do not accept any def for CallDOM.");
1197 return;
1198 }
1199
1200 case Arrayify:
1201 case ArrayifyToStructure:
1202 read(JSCell_structureID);
1203 read(JSCell_indexingType);
1204 read(JSObject_butterfly);
1205 write(JSCell_structureID);
1206 write(JSCell_indexingType);
1207 write(JSObject_butterfly);
1208 write(Watchpoint_fire);
1209 return;
1210
1211 case GetIndexedPropertyStorage:
1212 if (node->arrayMode().type() == Array::String) {
1213 def(PureValue(node, node->arrayMode().asWord()));
1214 return;
1215 }
1216 read(MiscFields);
1217 def(HeapLocation(IndexedPropertyStorageLoc, MiscFields, node->child1()), LazyNode(node));
1218 return;
1219
1220 case GetTypedArrayByteOffset:
1221 read(MiscFields);
1222 def(HeapLocation(TypedArrayByteOffsetLoc, MiscFields, node->child1()), LazyNode(node));
1223 return;
1224
1225 case GetPrototypeOf: {
1226 switch (node->child1().useKind()) {
1227 case ArrayUse:
1228 case FunctionUse:
1229 case FinalObjectUse:
1230 read(JSCell_structureID);
1231 read(JSObject_butterfly);
1232 read(NamedProperties); // Poly proto could load prototype from its slot.
1233 def(HeapLocation(PrototypeLoc, NamedProperties, node->child1()), LazyNode(node));
1234 return;
1235 default:
1236 read(World);
1237 write(Heap);
1238 return;
1239 }
1240 }
1241
1242 case GetByOffset:
1243 case GetGetterSetterByOffset: {
1244 unsigned identifierNumber = node->storageAccessData().identifierNumber;
1245 AbstractHeap heap(NamedProperties, identifierNumber);
1246 read(heap);
1247 def(HeapLocation(NamedPropertyLoc, heap, node->child2()), LazyNode(node));
1248 return;
1249 }
1250
1251 case TryGetById: {
1252 read(Heap);
1253 return;
1254 }
1255
1256 case MultiGetByOffset: {
1257 read(JSCell_structureID);
1258 read(JSObject_butterfly);
1259 AbstractHeap heap(NamedProperties, node->multiGetByOffsetData().identifierNumber);
1260 read(heap);
1261 def(HeapLocation(NamedPropertyLoc, heap, node->child1()), LazyNode(node));
1262 return;
1263 }
1264
1265 case MultiPutByOffset: {
1266 read(JSCell_structureID);
1267 read(JSObject_butterfly);
1268 AbstractHeap heap(NamedProperties, node->multiPutByOffsetData().identifierNumber);
1269 write(heap);
1270 if (node->multiPutByOffsetData().writesStructures())
1271 write(JSCell_structureID);
1272 if (node->multiPutByOffsetData().reallocatesStorage())
1273 write(JSObject_butterfly);
1274 def(HeapLocation(NamedPropertyLoc, heap, node->child1()), LazyNode(node->child2().node()));
1275 return;
1276 }
1277
1278 case PutByOffset: {
1279 unsigned identifierNumber = node->storageAccessData().identifierNumber;
1280 AbstractHeap heap(NamedProperties, identifierNumber);
1281 write(heap);
1282 def(HeapLocation(NamedPropertyLoc, heap, node->child2()), LazyNode(node->child3().node()));
1283 return;
1284 }
1285
1286 case GetArrayLength: {
1287 ArrayMode mode = node->arrayMode();
1288 switch (mode.type()) {
1289 case Array::Undecided:
1290 case Array::Int32:
1291 case Array::Double:
1292 case Array::Contiguous:
1293 case Array::ArrayStorage:
1294 case Array::SlowPutArrayStorage:
1295 read(Butterfly_publicLength);
1296 def(HeapLocation(ArrayLengthLoc, Butterfly_publicLength, node->child1()), LazyNode(node));
1297 return;
1298
1299 case Array::String:
1300 def(PureValue(node, mode.asWord()));
1301 return;
1302
1303 case Array::DirectArguments:
1304 case Array::ScopedArguments:
1305 read(MiscFields);
1306 def(HeapLocation(ArrayLengthLoc, MiscFields, node->child1()), LazyNode(node));
1307 return;
1308
1309 default:
1310 ASSERT(mode.isSomeTypedArrayView());
1311 read(MiscFields);
1312 def(HeapLocation(ArrayLengthLoc, MiscFields, node->child1()), LazyNode(node));
1313 return;
1314 }
1315 }
1316
1317 case GetVectorLength: {
1318 ArrayMode mode = node->arrayMode();
1319 switch (mode.type()) {
1320 case Array::ArrayStorage:
1321 case Array::SlowPutArrayStorage:
1322 read(Butterfly_vectorLength);
1323 def(HeapLocation(VectorLengthLoc, Butterfly_vectorLength, node->child1()), LazyNode(node));
1324 return;
1325
1326 default:
1327 RELEASE_ASSERT_NOT_REACHED();
1328 return;
1329 }
1330 }
1331
1332 case GetClosureVar:
1333 read(AbstractHeap(ScopeProperties, node->scopeOffset().offset()));
1334 def(HeapLocation(ClosureVariableLoc, AbstractHeap(ScopeProperties, node->scopeOffset().offset()), node->child1()), LazyNode(node));
1335 return;
1336
1337 case PutClosureVar:
1338 write(AbstractHeap(ScopeProperties, node->scopeOffset().offset()));
1339 def(HeapLocation(ClosureVariableLoc, AbstractHeap(ScopeProperties, node->scopeOffset().offset()), node->child1()), LazyNode(node->child2().node()));
1340 return;
1341
1342 case GetInternalField: {
1343 AbstractHeap heap(JSPromiseFields, node->internalFieldIndex());
1344 read(heap);
1345 def(HeapLocation(PromiseInternalFieldLoc, heap, node->child1()), LazyNode(node));
1346 return;
1347 }
1348
1349 case PutInternalField: {
1350 AbstractHeap heap(JSPromiseFields, node->internalFieldIndex());
1351 write(heap);
1352 def(HeapLocation(PromiseInternalFieldLoc, heap, node->child1()), LazyNode(node->child2().node()));
1353 return;
1354 }
1355
1356 case GetRegExpObjectLastIndex:
1357 read(RegExpObject_lastIndex);
1358 def(HeapLocation(RegExpObjectLastIndexLoc, RegExpObject_lastIndex, node->child1()), LazyNode(node));
1359 return;
1360
1361 case SetRegExpObjectLastIndex:
1362 write(RegExpObject_lastIndex);
1363 def(HeapLocation(RegExpObjectLastIndexLoc, RegExpObject_lastIndex, node->child1()), LazyNode(node->child2().node()));
1364 return;
1365
1366 case RecordRegExpCachedResult:
1367 write(RegExpState);
1368 return;
1369
1370 case GetFromArguments: {
1371 AbstractHeap heap(DirectArgumentsProperties, node->capturedArgumentsOffset().offset());
1372 read(heap);
1373 def(HeapLocation(DirectArgumentsLoc, heap, node->child1()), LazyNode(node));
1374 return;
1375 }
1376
1377 case PutToArguments: {
1378 AbstractHeap heap(DirectArgumentsProperties, node->capturedArgumentsOffset().offset());
1379 write(heap);
1380 def(HeapLocation(DirectArgumentsLoc, heap, node->child1()), LazyNode(node->child2().node()));
1381 return;
1382 }
1383
1384 case GetArgument: {
1385 read(Stack);
1386 // FIXME: It would be trivial to have a def here.
1387 // https://bugs.webkit.org/show_bug.cgi?id=143077
1388 return;
1389 }
1390
1391 case GetGlobalVar:
1392 case GetGlobalLexicalVariable:
1393 read(AbstractHeap(Absolute, node->variablePointer()));
1394 def(HeapLocation(GlobalVariableLoc, AbstractHeap(Absolute, node->variablePointer())), LazyNode(node));
1395 return;
1396
1397 case PutGlobalVariable:
1398 write(AbstractHeap(Absolute, node->variablePointer()));
1399 def(HeapLocation(GlobalVariableLoc, AbstractHeap(Absolute, node->variablePointer())), LazyNode(node->child2().node()));
1400 return;
1401
1402 case NewArrayWithSize:
1403 read(HeapObjectCount);
1404 write(HeapObjectCount);
1405 return;
1406
1407 case NewTypedArray:
1408 switch (node->child1().useKind()) {
1409 case Int32Use:
1410 read(HeapObjectCount);
1411 write(HeapObjectCount);
1412 return;
1413 case UntypedUse:
1414 read(World);
1415 write(Heap);
1416 return;
1417 default:
1418 DFG_CRASH(graph, node, "Bad use kind");
1419 }
1420 break;
1421
1422 case NewArrayWithSpread: {
1423 // This also reads from JSFixedArray's data store, but we don't have any way of describing that yet.
1424 read(HeapObjectCount);
1425 for (unsigned i = 0; i < node->numChildren(); i++) {
1426 Node* child = graph.varArgChild(node, i).node();
1427 if (child->op() == PhantomSpread) {
1428 read(Stack);
1429 break;
1430 }
1431 }
1432 write(HeapObjectCount);
1433 return;
1434 }
1435
1436 case Spread: {
1437 if (node->child1()->op() == PhantomNewArrayBuffer) {
1438 read(MiscFields);
1439 return;
1440 }
1441
1442 if (node->child1()->op() == PhantomCreateRest) {
1443 read(Stack);
1444 write(HeapObjectCount);
1445 return;
1446 }
1447
1448 read(World);
1449 write(Heap);
1450 return;
1451 }
1452
1453 case NewArray: {
1454 read(HeapObjectCount);
1455 write(HeapObjectCount);
1456
1457 unsigned numElements = node->numChildren();
1458
1459 def(HeapLocation(ArrayLengthLoc, Butterfly_publicLength, node),
1460 LazyNode(graph.freeze(jsNumber(numElements))));
1461
1462 if (!numElements)
1463 return;
1464
1465 AbstractHeap heap;
1466 LocationKind indexedPropertyLoc;
1467 switch (node->indexingType()) {
1468 case ALL_DOUBLE_INDEXING_TYPES:
1469 heap = IndexedDoubleProperties;
1470 indexedPropertyLoc = IndexedPropertyDoubleLoc;
1471 break;
1472
1473 case ALL_INT32_INDEXING_TYPES:
1474 heap = IndexedInt32Properties;
1475 indexedPropertyLoc = IndexedPropertyJSLoc;
1476 break;
1477
1478 case ALL_CONTIGUOUS_INDEXING_TYPES:
1479 heap = IndexedContiguousProperties;
1480 indexedPropertyLoc = IndexedPropertyJSLoc;
1481 break;
1482
1483 default:
1484 return;
1485 }
1486
1487 if (numElements < graph.m_uint32ValuesInUse.size()) {
1488 for (unsigned operandIdx = 0; operandIdx < numElements; ++operandIdx) {
1489 Edge use = graph.m_varArgChildren[node->firstChild() + operandIdx];
1490 def(HeapLocation(indexedPropertyLoc, heap, node, LazyNode(graph.freeze(jsNumber(operandIdx)))),
1491 LazyNode(use.node()));
1492 }
1493 } else {
1494 for (uint32_t operandIdx : graph.m_uint32ValuesInUse) {
1495 if (operandIdx >= numElements)
1496 continue;
1497 Edge use = graph.m_varArgChildren[node->firstChild() + operandIdx];
1498 // operandIdx comes from graph.m_uint32ValuesInUse and thus is guaranteed to be already frozen
1499 def(HeapLocation(indexedPropertyLoc, heap, node, LazyNode(graph.freeze(jsNumber(operandIdx)))),
1500 LazyNode(use.node()));
1501 }
1502 }
1503 return;
1504 }
1505
1506 case NewArrayBuffer: {
1507 read(HeapObjectCount);
1508 write(HeapObjectCount);
1509
1510 auto* array = node->castOperand<JSImmutableButterfly*>();
1511 unsigned numElements = array->length();
1512 def(HeapLocation(ArrayLengthLoc, Butterfly_publicLength, node),
1513 LazyNode(graph.freeze(jsNumber(numElements))));
1514
1515 AbstractHeap heap;
1516 LocationKind indexedPropertyLoc;
1517 NodeType op = JSConstant;
1518 switch (node->indexingType()) {
1519 case ALL_DOUBLE_INDEXING_TYPES:
1520 heap = IndexedDoubleProperties;
1521 indexedPropertyLoc = IndexedPropertyDoubleLoc;
1522 op = DoubleConstant;
1523 break;
1524
1525 case ALL_INT32_INDEXING_TYPES:
1526 heap = IndexedInt32Properties;
1527 indexedPropertyLoc = IndexedPropertyJSLoc;
1528 break;
1529
1530 case ALL_CONTIGUOUS_INDEXING_TYPES:
1531 heap = IndexedContiguousProperties;
1532 indexedPropertyLoc = IndexedPropertyJSLoc;
1533 break;
1534
1535 default:
1536 return;
1537 }
1538
1539 if (numElements < graph.m_uint32ValuesInUse.size()) {
1540 for (unsigned index = 0; index < numElements; ++index) {
1541 def(HeapLocation(indexedPropertyLoc, heap, node, LazyNode(graph.freeze(jsNumber(index)))),
1542 LazyNode(graph.freeze(array->get(index)), op));
1543 }
1544 } else {
1545 Vector<uint32_t> possibleIndices;
1546 for (uint32_t index : graph.m_uint32ValuesInUse) {
1547 if (index >= numElements)
1548 continue;
1549 possibleIndices.append(index);
1550 }
1551 for (uint32_t index : possibleIndices) {
1552 def(HeapLocation(indexedPropertyLoc, heap, node, LazyNode(graph.freeze(jsNumber(index)))),
1553 LazyNode(graph.freeze(array->get(index)), op));
1554 }
1555 }
1556 return;
1557 }
1558
1559 case CreateRest: {
1560 if (!graph.isWatchingHavingABadTimeWatchpoint(node)) {
1561 // This means we're already having a bad time.
1562 read(World);
1563 write(Heap);
1564 return;
1565 }
1566 read(Stack);
1567 read(HeapObjectCount);
1568 write(HeapObjectCount);
1569 return;
1570 }
1571
1572 case ObjectCreate: {
1573 switch (node->child1().useKind()) {
1574 case ObjectUse:
1575 read(HeapObjectCount);
1576 write(HeapObjectCount);
1577 return;
1578 case UntypedUse:
1579 read(World);
1580 write(Heap);
1581 return;
1582 default:
1583 RELEASE_ASSERT_NOT_REACHED();
1584 return;
1585 }
1586 }
1587
1588 case NewObject:
1589 case NewPromise:
1590 case NewGenerator:
1591 case NewAsyncGenerator:
1592 case NewRegexp:
1593 case NewSymbol:
1594 case NewStringObject:
1595 case PhantomNewObject:
1596 case MaterializeNewObject:
1597 case PhantomNewFunction:
1598 case PhantomNewGeneratorFunction:
1599 case PhantomNewAsyncFunction:
1600 case PhantomNewAsyncGeneratorFunction:
1601 case PhantomCreateActivation:
1602 case MaterializeCreateActivation:
1603 case PhantomNewRegexp:
1604 read(HeapObjectCount);
1605 write(HeapObjectCount);
1606 return;
1607
1608 case NewFunction:
1609 case NewGeneratorFunction:
1610 case NewAsyncGeneratorFunction:
1611 case NewAsyncFunction:
1612 if (node->castOperand<FunctionExecutable*>()->singleton().isStillValid())
1613 write(Watchpoint_fire);
1614 read(HeapObjectCount);
1615 write(HeapObjectCount);
1616 return;
1617
1618 case RegExpExec:
1619 case RegExpTest:
1620 // Even if we've proven known input types as RegExpObject and String,
1621 // accessing lastIndex is effectful if it's a global regexp.
1622 read(World);
1623 write(Heap);
1624 return;
1625
1626 case RegExpMatchFast:
1627 read(RegExpState);
1628 read(RegExpObject_lastIndex);
1629 write(RegExpState);
1630 write(RegExpObject_lastIndex);
1631 return;
1632
1633 case RegExpExecNonGlobalOrSticky:
1634 case RegExpMatchFastGlobal:
1635 read(RegExpState);
1636 write(RegExpState);
1637 return;
1638
1639 case StringReplace:
1640 case StringReplaceRegExp:
1641 if (node->child1().useKind() == StringUse
1642 && node->child2().useKind() == RegExpObjectUse
1643 && node->child3().useKind() == StringUse) {
1644 read(RegExpState);
1645 read(RegExpObject_lastIndex);
1646 write(RegExpState);
1647 write(RegExpObject_lastIndex);
1648 return;
1649 }
1650 read(World);
1651 write(Heap);
1652 return;
1653
1654 case StringCharAt:
1655 if (node->arrayMode().isOutOfBounds()) {
1656 read(World);
1657 write(Heap);
1658 return;
1659 }
1660 def(PureValue(node));
1661 return;
1662
1663 case CompareBelow:
1664 case CompareBelowEq:
1665 def(PureValue(node));
1666 return;
1667
1668 case CompareEq:
1669 case CompareLess:
1670 case CompareLessEq:
1671 case CompareGreater:
1672 case CompareGreaterEq:
1673 if (node->isBinaryUseKind(StringUse)) {
1674 read(HeapObjectCount);
1675 write(HeapObjectCount);
1676 return;
1677 }
1678
1679 if (node->isBinaryUseKind(UntypedUse)) {
1680 read(World);
1681 write(Heap);
1682 return;
1683 }
1684
1685 def(PureValue(node));
1686 return;
1687
1688 case ToString:
1689 case CallStringConstructor:
1690 switch (node->child1().useKind()) {
1691 case CellUse:
1692 case UntypedUse:
1693 read(World);
1694 write(Heap);
1695 return;
1696
1697 case StringObjectUse:
1698 case StringOrStringObjectUse:
1699 // These two StringObjectUse's are pure because if we emit this node with either
1700 // of these UseKinds, we'll first emit a StructureCheck ensuring that we're the
1701 // original String or StringObject structure. Therefore, we don't have an overridden
1702 // valueOf, etc.
1703
1704 case Int32Use:
1705 case Int52RepUse:
1706 case DoubleRepUse:
1707 case NotCellUse:
1708 def(PureValue(node));
1709 return;
1710
1711 default:
1712 RELEASE_ASSERT_NOT_REACHED();
1713 return;
1714 }
1715
1716 case CountExecution:
1717 case SuperSamplerBegin:
1718 case SuperSamplerEnd:
1719 read(InternalState);
1720 write(InternalState);
1721 return;
1722
1723 case LogShadowChickenPrologue:
1724 case LogShadowChickenTail:
1725 write(SideState);
1726 return;
1727
1728 case MapHash:
1729 def(PureValue(node));
1730 return;
1731
1732 case NormalizeMapKey:
1733 def(PureValue(node));
1734 return;
1735
1736 case GetMapBucket: {
1737 Edge& mapEdge = node->child1();
1738 Edge& keyEdge = node->child2();
1739 AbstractHeapKind heap = (mapEdge.useKind() == MapObjectUse) ? JSMapFields : JSSetFields;
1740 read(heap);
1741 def(HeapLocation(MapBucketLoc, heap, mapEdge, keyEdge), LazyNode(node));
1742 return;
1743 }
1744
1745 case GetMapBucketHead: {
1746 Edge& mapEdge = node->child1();
1747 AbstractHeapKind heap = (mapEdge.useKind() == MapObjectUse) ? JSMapFields : JSSetFields;
1748 read(heap);
1749 def(HeapLocation(MapBucketHeadLoc, heap, mapEdge), LazyNode(node));
1750 return;
1751 }
1752
1753 case GetMapBucketNext: {
1754 AbstractHeapKind heap = (node->bucketOwnerType() == BucketOwnerType::Map) ? JSMapFields : JSSetFields;
1755 read(heap);
1756 Edge& bucketEdge = node->child1();
1757 def(HeapLocation(MapBucketNextLoc, heap, bucketEdge), LazyNode(node));
1758 return;
1759 }
1760
1761 case LoadKeyFromMapBucket: {
1762 AbstractHeapKind heap = (node->bucketOwnerType() == BucketOwnerType::Map) ? JSMapFields : JSSetFields;
1763 read(heap);
1764 Edge& bucketEdge = node->child1();
1765 def(HeapLocation(MapBucketKeyLoc, heap, bucketEdge), LazyNode(node));
1766 return;
1767 }
1768
1769 case LoadValueFromMapBucket: {
1770 AbstractHeapKind heap = (node->bucketOwnerType() == BucketOwnerType::Map) ? JSMapFields : JSSetFields;
1771 read(heap);
1772 Edge& bucketEdge = node->child1();
1773 def(HeapLocation(MapBucketValueLoc, heap, bucketEdge), LazyNode(node));
1774 return;
1775 }
1776
1777 case WeakMapGet: {
1778 Edge& mapEdge = node->child1();
1779 Edge& keyEdge = node->child2();
1780 AbstractHeapKind heap = (mapEdge.useKind() == WeakMapObjectUse) ? JSWeakMapFields : JSWeakSetFields;
1781 read(heap);
1782 def(HeapLocation(WeakMapGetLoc, heap, mapEdge, keyEdge), LazyNode(node));
1783 return;
1784 }
1785
1786 case SetAdd: {
1787 Edge& mapEdge = node->child1();
1788 Edge& keyEdge = node->child2();
1789 write(JSSetFields);
1790 def(HeapLocation(MapBucketLoc, JSSetFields, mapEdge, keyEdge), LazyNode(node));
1791 return;
1792 }
1793
1794 case MapSet: {
1795 Edge& mapEdge = graph.varArgChild(node, 0);
1796 Edge& keyEdge = graph.varArgChild(node, 1);
1797 write(JSMapFields);
1798 def(HeapLocation(MapBucketLoc, JSMapFields, mapEdge, keyEdge), LazyNode(node));
1799 return;
1800 }
1801
1802 case WeakSetAdd: {
1803 Edge& mapEdge = node->child1();
1804 Edge& keyEdge = node->child2();
1805 write(JSWeakSetFields);
1806 def(HeapLocation(WeakMapGetLoc, JSWeakSetFields, mapEdge, keyEdge), LazyNode(keyEdge.node()));
1807 return;
1808 }
1809
1810 case WeakMapSet: {
1811 Edge& mapEdge = graph.varArgChild(node, 0);
1812 Edge& keyEdge = graph.varArgChild(node, 1);
1813 Edge& valueEdge = graph.varArgChild(node, 2);
1814 write(JSWeakMapFields);
1815 def(HeapLocation(WeakMapGetLoc, JSWeakMapFields, mapEdge, keyEdge), LazyNode(valueEdge.node()));
1816 return;
1817 }
1818
1819 case ExtractValueFromWeakMapGet:
1820 def(PureValue(node));
1821 return;
1822
1823 case StringSlice:
1824 def(PureValue(node));
1825 return;
1826
1827 case ToLowerCase:
1828 def(PureValue(node));
1829 return;
1830
1831 case NumberToStringWithValidRadixConstant:
1832 def(PureValue(node, node->validRadixConstant()));
1833 return;
1834
1835 case DateGetTime:
1836 case DateGetInt32OrNaN: {
1837 read(JSDateFields);
1838 def(HeapLocation(DateFieldLoc, AbstractHeap(JSDateFields, static_cast<uint64_t>(node->intrinsic())), node->child1()), LazyNode(node));
1839 return;
1840 }
1841
1842 case DataViewGetFloat:
1843 case DataViewGetInt: {
1844 read(MiscFields);
1845 read(TypedArrayProperties);
1846 LocationKind indexedPropertyLoc = indexedPropertyLocForResultType(node->result());
1847 def(HeapLocation(indexedPropertyLoc, AbstractHeap(TypedArrayProperties, node->dataViewData().asQuadWord),
1848 node->child1(), node->child2(), node->child3()), LazyNode(node));
1849 return;
1850 }
1851
1852 case DataViewSet: {
1853 read(MiscFields);
1854 read(TypedArrayProperties);
1855 write(TypedArrayProperties);
1856 return;
1857 }
1858
1859 case LastNodeType:
1860 RELEASE_ASSERT_NOT_REACHED();
1861 return;
1862 }
1863
1864 DFG_CRASH(graph, node, toCString("Unrecognized node type: ", Graph::opName(node->op())).data());
1865}
1866
1867class NoOpClobberize {
1868public:
1869 NoOpClobberize() { }
1870 template<typename... T>
1871 void operator()(T...) const { }
1872};
1873
1874class CheckClobberize {
1875public:
1876 CheckClobberize()
1877 : m_result(false)
1878 {
1879 }
1880
1881 template<typename... T>
1882 void operator()(T...) const { m_result = true; }
1883
1884 bool result() const { return m_result; }
1885
1886private:
1887 mutable bool m_result;
1888};
1889
1890bool doesWrites(Graph&, Node*);
1891
1892class AbstractHeapOverlaps {
1893public:
1894 AbstractHeapOverlaps(AbstractHeap heap)
1895 : m_heap(heap)
1896 , m_result(false)
1897 {
1898 }
1899
1900 void operator()(AbstractHeap otherHeap) const
1901 {
1902 if (m_result)
1903 return;
1904 m_result = m_heap.overlaps(otherHeap);
1905 }
1906
1907 bool result() const { return m_result; }
1908
1909private:
1910 AbstractHeap m_heap;
1911 mutable bool m_result;
1912};
1913
1914bool accessesOverlap(Graph&, Node*, AbstractHeap);
1915bool writesOverlap(Graph&, Node*, AbstractHeap);
1916
1917bool clobbersHeap(Graph&, Node*);
1918
1919// We would have used bind() for these, but because of the overlaoding that we are doing,
1920// it's quite a bit of clearer to just write this out the traditional way.
1921
1922template<typename T>
1923class ReadMethodClobberize {
1924public:
1925 ReadMethodClobberize(T& value)
1926 : m_value(value)
1927 {
1928 }
1929
1930 void operator()(AbstractHeap heap) const
1931 {
1932 m_value.read(heap);
1933 }
1934private:
1935 T& m_value;
1936};
1937
1938template<typename T>
1939class WriteMethodClobberize {
1940public:
1941 WriteMethodClobberize(T& value)
1942 : m_value(value)
1943 {
1944 }
1945
1946 void operator()(AbstractHeap heap) const
1947 {
1948 m_value.write(heap);
1949 }
1950private:
1951 T& m_value;
1952};
1953
1954template<typename T>
1955class DefMethodClobberize {
1956public:
1957 DefMethodClobberize(T& value)
1958 : m_value(value)
1959 {
1960 }
1961
1962 void operator()(PureValue value) const
1963 {
1964 m_value.def(value);
1965 }
1966
1967 void operator()(HeapLocation location, LazyNode node) const
1968 {
1969 m_value.def(location, node);
1970 }
1971
1972private:
1973 T& m_value;
1974};
1975
1976template<typename Adaptor>
1977void clobberize(Graph& graph, Node* node, Adaptor& adaptor)
1978{
1979 ReadMethodClobberize<Adaptor> read(adaptor);
1980 WriteMethodClobberize<Adaptor> write(adaptor);
1981 DefMethodClobberize<Adaptor> def(adaptor);
1982 clobberize(graph, node, read, write, def);
1983}
1984
1985} } // namespace JSC::DFG
1986
1987#endif // ENABLE(DFG_JIT)
1988