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