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