We need to model effects of Spread(@PhantomCreateRest) in Clobberize/PreciseLocalClob...
[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 CheckStringIdent:
421         def(PureValue(CheckStringIdent, AdjacencyList(AdjacencyList::Fixed, node->child1()), node->uidOperand()));
422         return;
423
424     case ConstantStoragePointer:
425         def(PureValue(node, node->storagePointer()));
426         return;
427          
428     case MovHint:
429     case ZombieHint:
430     case ExitOK:
431     case KillStack:
432     case Upsilon:
433     case Phi:
434     case PhantomLocal:
435     case SetArgument:
436     case Jump:
437     case Branch:
438     case Switch:
439     case EntrySwitch:
440     case ForceOSRExit:
441     case CPUIntrinsic:
442     case CheckBadCell:
443     case Return:
444     case Unreachable:
445     case CheckTierUpInLoop:
446     case CheckTierUpAtReturn:
447     case CheckTierUpAndOSREnter:
448     case LoopHint:
449     case ProfileType:
450     case ProfileControlFlow:
451     case PutHint:
452     case InitializeEntrypointArguments:
453         write(SideState);
454         return;
455         
456     case StoreBarrier:
457         read(JSCell_cellState);
458         write(JSCell_cellState);
459         return;
460         
461     case FencedStoreBarrier:
462         read(Heap);
463         write(JSCell_cellState);
464         return;
465
466     case CheckTraps:
467         if (Options::usePollingTraps()) {
468             read(InternalState);
469             write(InternalState);
470         } else
471             write(Watchpoint_fire);
472         return;
473
474     case InvalidationPoint:
475         write(SideState);
476         def(HeapLocation(InvalidationPointLoc, Watchpoint_fire), LazyNode(node));
477         return;
478
479     case Flush:
480         read(AbstractHeap(Stack, node->local()));
481         write(SideState);
482         return;
483
484     case NotifyWrite:
485         write(Watchpoint_fire);
486         write(SideState);
487         return;
488
489     case PushWithScope: {
490         read(World);
491         write(HeapObjectCount);
492         return;
493     }
494
495     case CreateActivation: {
496         SymbolTable* table = node->castOperand<SymbolTable*>();
497         if (table->singletonScope()->isStillValid())
498             write(Watchpoint_fire);
499         read(HeapObjectCount);
500         write(HeapObjectCount);
501         return;
502     }
503
504     case CreateDirectArguments:
505     case CreateScopedArguments:
506     case CreateClonedArguments:
507         read(Stack);
508         read(HeapObjectCount);
509         write(HeapObjectCount);
510         return;
511
512     case PhantomDirectArguments:
513     case PhantomClonedArguments:
514         // DFG backend requires that the locals that this reads are flushed. FTL backend can handle those
515         // locals being promoted.
516         if (!isFTL(graph.m_plan.mode))
517             read(Stack);
518         
519         // Even though it's phantom, it still has the property that one can't be replaced with another.
520         read(HeapObjectCount);
521         write(HeapObjectCount);
522         return;
523
524     case PhantomSpread:
525     case PhantomNewArrayWithSpread:
526     case PhantomCreateRest:
527         // Even though it's phantom, it still has the property that one can't be replaced with another.
528         read(HeapObjectCount);
529         write(HeapObjectCount);
530         return;
531
532     case ToObject:
533         read(World);
534         write(Heap);
535         return;
536
537     case CallObjectConstructor:
538         read(HeapObjectCount);
539         write(HeapObjectCount);
540         return;
541
542     case ToThis:
543     case CreateThis:
544         read(MiscFields);
545         read(HeapObjectCount);
546         write(HeapObjectCount);
547         return;
548
549     case IsObjectOrNull:
550         read(MiscFields);
551         def(HeapLocation(IsObjectOrNullLoc, MiscFields, node->child1()), LazyNode(node));
552         return;
553         
554     case IsFunction:
555         read(MiscFields);
556         def(HeapLocation(IsFunctionLoc, MiscFields, node->child1()), LazyNode(node));
557         return;
558
559     case ArraySlice:
560         read(MiscFields);
561         read(JSCell_indexingType);
562         read(JSCell_structureID);
563         read(JSObject_butterfly);
564         read(Butterfly_publicLength);
565         read(IndexedDoubleProperties);
566         read(IndexedInt32Properties);
567         read(IndexedContiguousProperties);
568         read(HeapObjectCount);
569         write(HeapObjectCount);
570         return;
571
572     case ArrayIndexOf: {
573         // FIXME: Should support a CSE rule.
574         // https://bugs.webkit.org/show_bug.cgi?id=173173
575         read(MiscFields);
576         read(JSCell_indexingType);
577         read(JSCell_structureID);
578         read(JSObject_butterfly);
579         read(Butterfly_publicLength);
580         switch (node->arrayMode().type()) {
581         case Array::Double:
582             read(IndexedDoubleProperties);
583             return;
584         case Array::Int32:
585             read(IndexedInt32Properties);
586             return;
587         case Array::Contiguous:
588             read(IndexedContiguousProperties);
589             return;
590         default:
591             RELEASE_ASSERT_NOT_REACHED();
592             return;
593         }
594         return;
595     }
596         
597     case GetById:
598     case GetByIdFlush:
599     case GetByIdWithThis:
600     case GetByValWithThis:
601     case PutById:
602     case PutByIdWithThis:
603     case PutByValWithThis:
604     case PutByIdFlush:
605     case PutByIdDirect:
606     case PutGetterById:
607     case PutSetterById:
608     case PutGetterSetterById:
609     case PutGetterByVal:
610     case PutSetterByVal:
611     case DefineDataProperty:
612     case DefineAccessorProperty:
613     case DeleteById:
614     case DeleteByVal:
615     case ArrayPush:
616     case ArrayPop:
617     case Call:
618     case DirectCall:
619     case TailCallInlinedCaller:
620     case DirectTailCallInlinedCaller:
621     case Construct:
622     case DirectConstruct:
623     case CallVarargs:
624     case CallForwardVarargs:
625     case TailCallVarargsInlinedCaller:
626     case TailCallForwardVarargsInlinedCaller:
627     case ConstructVarargs:
628     case ConstructForwardVarargs:
629     case ToPrimitive:
630     case In:
631     case HasOwnProperty:
632     case ValueAdd:
633     case SetFunctionName:
634     case GetDynamicVar:
635     case PutDynamicVar:
636     case ResolveScopeForHoistingFuncDeclInEval:
637     case ResolveScope:
638         read(World);
639         write(Heap);
640         return;
641
642     case AtomicsAdd:
643     case AtomicsAnd:
644     case AtomicsCompareExchange:
645     case AtomicsExchange:
646     case AtomicsLoad:
647     case AtomicsOr:
648     case AtomicsStore:
649     case AtomicsSub:
650     case AtomicsXor: {
651         unsigned numExtraArgs = numExtraAtomicsArgs(node->op());
652         Edge storageEdge = graph.child(node, 2 + numExtraArgs);
653         if (!storageEdge) {
654             read(World);
655             write(Heap);
656             return;
657         }
658         read(TypedArrayProperties);
659         read(MiscFields);
660         write(TypedArrayProperties);
661         return;
662     }
663
664     case CallEval:
665         ASSERT(!node->origin.semantic.inlineCallFrame);
666         read(AbstractHeap(Stack, graph.m_codeBlock->scopeRegister()));
667         read(AbstractHeap(Stack, virtualRegisterForArgument(0)));
668         read(World);
669         write(Heap);
670         return;
671
672     case Throw:
673     case ThrowStaticError:
674     case TailCall:
675     case DirectTailCall:
676     case TailCallVarargs:
677     case TailCallForwardVarargs:
678         read(World);
679         write(SideState);
680         return;
681         
682     case GetGetter:
683         read(GetterSetter_getter);
684         def(HeapLocation(GetterLoc, GetterSetter_getter, node->child1()), LazyNode(node));
685         return;
686         
687     case GetSetter:
688         read(GetterSetter_setter);
689         def(HeapLocation(SetterLoc, GetterSetter_setter, node->child1()), LazyNode(node));
690         return;
691         
692     case GetCallee:
693         read(AbstractHeap(Stack, CallFrameSlot::callee));
694         def(HeapLocation(StackLoc, AbstractHeap(Stack, CallFrameSlot::callee)), LazyNode(node));
695         return;
696         
697     case GetArgumentCountIncludingThis:
698         read(AbstractHeap(Stack, CallFrameSlot::argumentCount));
699         def(HeapLocation(StackPayloadLoc, AbstractHeap(Stack, CallFrameSlot::argumentCount)), LazyNode(node));
700         return;
701
702     case GetRestLength:
703         read(Stack);
704         return;
705         
706     case GetLocal:
707         read(AbstractHeap(Stack, node->local()));
708         def(HeapLocation(StackLoc, AbstractHeap(Stack, node->local())), LazyNode(node));
709         return;
710         
711     case SetLocal:
712         write(AbstractHeap(Stack, node->local()));
713         def(HeapLocation(StackLoc, AbstractHeap(Stack, node->local())), LazyNode(node->child1().node()));
714         return;
715         
716     case GetStack: {
717         AbstractHeap heap(Stack, node->stackAccessData()->local);
718         read(heap);
719         def(HeapLocation(StackLoc, heap), LazyNode(node));
720         return;
721     }
722         
723     case PutStack: {
724         AbstractHeap heap(Stack, node->stackAccessData()->local);
725         write(heap);
726         def(HeapLocation(StackLoc, heap), LazyNode(node->child1().node()));
727         return;
728     }
729         
730     case LoadVarargs: {
731         read(World);
732         write(Heap);
733         LoadVarargsData* data = node->loadVarargsData();
734         write(AbstractHeap(Stack, data->count.offset()));
735         for (unsigned i = data->limit; i--;)
736             write(AbstractHeap(Stack, data->start.offset() + static_cast<int>(i)));
737         return;
738     }
739         
740     case ForwardVarargs: {
741         // We could be way more precise here.
742         read(Stack);
743         
744         LoadVarargsData* data = node->loadVarargsData();
745         write(AbstractHeap(Stack, data->count.offset()));
746         for (unsigned i = data->limit; i--;)
747             write(AbstractHeap(Stack, data->start.offset() + static_cast<int>(i)));
748         return;
749     }
750         
751     case GetByVal: {
752         ArrayMode mode = node->arrayMode();
753         LocationKind indexedPropertyLoc = indexedPropertyLocForResultType(node->result());
754         switch (mode.type()) {
755         case Array::SelectUsingPredictions:
756         case Array::Unprofiled:
757         case Array::SelectUsingArguments:
758             // Assume the worst since we don't have profiling yet.
759             read(World);
760             write(Heap);
761             return;
762             
763         case Array::ForceExit:
764             write(SideState);
765             return;
766             
767         case Array::Generic:
768             read(World);
769             write(Heap);
770             return;
771             
772         case Array::String:
773             if (mode.isOutOfBounds()) {
774                 read(World);
775                 write(Heap);
776                 return;
777             }
778             // This appears to read nothing because it's only reading immutable data.
779             def(PureValue(node, mode.asWord()));
780             return;
781             
782         case Array::DirectArguments:
783             if (mode.isInBounds()) {
784                 read(DirectArgumentsProperties);
785                 def(HeapLocation(indexedPropertyLoc, DirectArgumentsProperties, node->child1(), node->child2()), LazyNode(node));
786                 return;
787             }
788             read(World);
789             write(Heap);
790             return;
791             
792         case Array::ScopedArguments:
793             read(ScopeProperties);
794             def(HeapLocation(indexedPropertyLoc, ScopeProperties, node->child1(), node->child2()), LazyNode(node));
795             return;
796             
797         case Array::Int32:
798             if (mode.isInBounds()) {
799                 read(Butterfly_publicLength);
800                 read(IndexedInt32Properties);
801                 def(HeapLocation(indexedPropertyLoc, IndexedInt32Properties, node->child1(), node->child2()), LazyNode(node));
802                 return;
803             }
804             read(World);
805             write(Heap);
806             return;
807             
808         case Array::Double:
809             if (mode.isInBounds()) {
810                 read(Butterfly_publicLength);
811                 read(IndexedDoubleProperties);
812                 def(HeapLocation(indexedPropertyLoc, IndexedDoubleProperties, node->child1(), node->child2()), LazyNode(node));
813                 return;
814             }
815             read(World);
816             write(Heap);
817             return;
818             
819         case Array::Contiguous:
820             if (mode.isInBounds()) {
821                 read(Butterfly_publicLength);
822                 read(IndexedContiguousProperties);
823                 def(HeapLocation(indexedPropertyLoc, IndexedContiguousProperties, node->child1(), node->child2()), LazyNode(node));
824                 return;
825             }
826             read(World);
827             write(Heap);
828             return;
829
830         case Array::Undecided:
831             def(PureValue(node));
832             return;
833             
834         case Array::ArrayStorage:
835         case Array::SlowPutArrayStorage:
836             if (mode.isInBounds()) {
837                 read(Butterfly_vectorLength);
838                 read(IndexedArrayStorageProperties);
839                 return;
840             }
841             read(World);
842             write(Heap);
843             return;
844             
845         case Array::Int8Array:
846         case Array::Int16Array:
847         case Array::Int32Array:
848         case Array::Uint8Array:
849         case Array::Uint8ClampedArray:
850         case Array::Uint16Array:
851         case Array::Uint32Array:
852         case Array::Float32Array:
853         case Array::Float64Array:
854             read(TypedArrayProperties);
855             read(MiscFields);
856             def(HeapLocation(indexedPropertyLoc, TypedArrayProperties, node->child1(), node->child2()), LazyNode(node));
857             return;
858         // We should not get an AnyTypedArray in a GetByVal as AnyTypedArray is only created from intrinsics, which
859         // are only added from Inline Caching a GetById.
860         case Array::AnyTypedArray:
861             DFG_CRASH(graph, node, "impossible array mode for get");
862             return;
863         }
864         RELEASE_ASSERT_NOT_REACHED();
865         return;
866     }
867         
868     case GetMyArgumentByVal:
869     case GetMyArgumentByValOutOfBounds: {
870         read(Stack);
871         // FIXME: It would be trivial to have a def here.
872         // https://bugs.webkit.org/show_bug.cgi?id=143077
873         return;
874     }
875
876     case PutByValDirect:
877     case PutByVal:
878     case PutByValAlias: {
879         ArrayMode mode = node->arrayMode();
880         Node* base = graph.varArgChild(node, 0).node();
881         Node* index = graph.varArgChild(node, 1).node();
882         Node* value = graph.varArgChild(node, 2).node();
883         LocationKind indexedPropertyLoc = indexedPropertyLocForResultType(node->result());
884
885         switch (mode.modeForPut().type()) {
886         case Array::SelectUsingPredictions:
887         case Array::SelectUsingArguments:
888         case Array::Unprofiled:
889         case Array::Undecided:
890             // Assume the worst since we don't have profiling yet.
891             read(World);
892             write(Heap);
893             return;
894             
895         case Array::ForceExit:
896             write(SideState);
897             return;
898             
899         case Array::Generic:
900             read(World);
901             write(Heap);
902             return;
903             
904         case Array::Int32:
905             if (node->arrayMode().isOutOfBounds()) {
906                 read(World);
907                 write(Heap);
908                 return;
909             }
910             read(Butterfly_publicLength);
911             read(Butterfly_vectorLength);
912             read(IndexedInt32Properties);
913             write(IndexedInt32Properties);
914             if (node->arrayMode().mayStoreToHole())
915                 write(Butterfly_publicLength);
916             def(HeapLocation(indexedPropertyLoc, IndexedInt32Properties, base, index), LazyNode(value));
917             return;
918             
919         case Array::Double:
920             if (node->arrayMode().isOutOfBounds()) {
921                 read(World);
922                 write(Heap);
923                 return;
924             }
925             read(Butterfly_publicLength);
926             read(Butterfly_vectorLength);
927             read(IndexedDoubleProperties);
928             write(IndexedDoubleProperties);
929             if (node->arrayMode().mayStoreToHole())
930                 write(Butterfly_publicLength);
931             def(HeapLocation(indexedPropertyLoc, IndexedDoubleProperties, base, index), LazyNode(value));
932             return;
933             
934         case Array::Contiguous:
935             if (node->arrayMode().isOutOfBounds()) {
936                 read(World);
937                 write(Heap);
938                 return;
939             }
940             read(Butterfly_publicLength);
941             read(Butterfly_vectorLength);
942             read(IndexedContiguousProperties);
943             write(IndexedContiguousProperties);
944             if (node->arrayMode().mayStoreToHole())
945                 write(Butterfly_publicLength);
946             def(HeapLocation(indexedPropertyLoc, IndexedContiguousProperties, base, index), LazyNode(value));
947             return;
948             
949         case Array::ArrayStorage:
950         case Array::SlowPutArrayStorage:
951             // Give up on life for now.
952             read(World);
953             write(Heap);
954             return;
955
956         case Array::Int8Array:
957         case Array::Int16Array:
958         case Array::Int32Array:
959         case Array::Uint8Array:
960         case Array::Uint8ClampedArray:
961         case Array::Uint16Array:
962         case Array::Uint32Array:
963         case Array::Float32Array:
964         case Array::Float64Array:
965             read(MiscFields);
966             write(TypedArrayProperties);
967             // FIXME: We can't def() anything here because these operations truncate their inputs.
968             // https://bugs.webkit.org/show_bug.cgi?id=134737
969             return;
970         case Array::AnyTypedArray:
971         case Array::String:
972         case Array::DirectArguments:
973         case Array::ScopedArguments:
974             DFG_CRASH(graph, node, "impossible array mode for put");
975             return;
976         }
977         RELEASE_ASSERT_NOT_REACHED();
978         return;
979     }
980         
981     case CheckStructureOrEmpty:
982     case CheckStructure:
983         read(JSCell_structureID);
984         return;
985
986     case CheckArray:
987         read(JSCell_indexingType);
988         read(JSCell_typeInfoType);
989         read(JSCell_structureID);
990         return;
991
992     case CheckTypeInfoFlags:
993         read(JSCell_typeInfoFlags);
994         def(HeapLocation(CheckTypeInfoFlagsLoc, JSCell_typeInfoFlags, node->child1()), LazyNode(node));
995         return;
996
997     case ParseInt:
998         // Note: We would have eliminated a ParseInt that has just a single child as an Int32Use inside fixup.
999         if (node->child1().useKind() == StringUse && (!node->child2() || node->child2().useKind() == Int32Use)) {
1000             def(PureValue(node));
1001             return;
1002         }
1003
1004         read(World);
1005         write(Heap);
1006         return;
1007
1008     case OverridesHasInstance:
1009         read(JSCell_typeInfoFlags);
1010         def(HeapLocation(OverridesHasInstanceLoc, JSCell_typeInfoFlags, node->child1()), LazyNode(node));
1011         return;
1012
1013     case InstanceOf:
1014         read(JSCell_structureID);
1015         def(HeapLocation(InstanceOfLoc, JSCell_structureID, node->child1(), node->child2()), LazyNode(node));
1016         return;
1017
1018     case InstanceOfCustom:
1019         read(World);
1020         write(Heap);
1021         return;
1022
1023     case PutStructure:
1024         read(JSObject_butterfly);
1025         write(JSCell_structureID);
1026         write(JSCell_typeInfoType);
1027         write(JSCell_typeInfoFlags);
1028         write(JSCell_indexingType);
1029         return;
1030         
1031     case AllocatePropertyStorage:
1032     case ReallocatePropertyStorage:
1033         read(HeapObjectCount);
1034         write(HeapObjectCount);
1035         return;
1036         
1037     case NukeStructureAndSetButterfly:
1038         write(JSObject_butterfly);
1039         write(JSCell_structureID);
1040         def(HeapLocation(ButterflyLoc, JSObject_butterfly, node->child1()), LazyNode(node->child2().node()));
1041         return;
1042         
1043     case GetButterfly:
1044         read(JSObject_butterfly);
1045         def(HeapLocation(ButterflyLoc, JSObject_butterfly, node->child1()), LazyNode(node));
1046         return;
1047
1048     case CheckSubClass:
1049         def(PureValue(node, node->classInfo()));
1050         return;
1051
1052     case CallDOMGetter: {
1053         DOMJIT::CallDOMGetterSnippet* snippet = node->callDOMGetterData()->snippet;
1054         if (!snippet) {
1055             read(World);
1056             write(Heap);
1057             return;
1058         }
1059         DOMJIT::Effect effect = snippet->effect;
1060         if (effect.reads) {
1061             if (effect.reads == DOMJIT::HeapRange::top())
1062                 read(World);
1063             else
1064                 read(AbstractHeap(DOMState, effect.reads.rawRepresentation()));
1065         }
1066         if (effect.writes) {
1067             if (effect.writes == DOMJIT::HeapRange::top())
1068                 write(Heap);
1069             else
1070                 write(AbstractHeap(DOMState, effect.writes.rawRepresentation()));
1071         }
1072         if (effect.def != DOMJIT::HeapRange::top()) {
1073             DOMJIT::HeapRange range = effect.def;
1074             if (range == DOMJIT::HeapRange::none())
1075                 def(PureValue(node, bitwise_cast<uintptr_t>(node->callDOMGetterData()->customAccessorGetter)));
1076             else {
1077                 // Def with heap location. We do not include "GlobalObject" for that since this information is included in the base node.
1078                 // We only see the DOMJIT getter here. So just including "base" is ok.
1079                 def(HeapLocation(DOMStateLoc, AbstractHeap(DOMState, range.rawRepresentation()), node->child1()), LazyNode(node));
1080             }
1081         }
1082         return;
1083     }
1084
1085     case CallDOM: {
1086         const DOMJIT::Signature* signature = node->signature();
1087         DOMJIT::Effect effect = signature->effect;
1088         if (effect.reads) {
1089             if (effect.reads == DOMJIT::HeapRange::top())
1090                 read(World);
1091             else
1092                 read(AbstractHeap(DOMState, effect.reads.rawRepresentation()));
1093         }
1094         if (effect.writes) {
1095             if (effect.writes == DOMJIT::HeapRange::top())
1096                 write(Heap);
1097             else
1098                 write(AbstractHeap(DOMState, effect.writes.rawRepresentation()));
1099         }
1100         ASSERT_WITH_MESSAGE(effect.def == DOMJIT::HeapRange::top(), "Currently, we do not accept any def for CallDOM.");
1101         return;
1102     }
1103
1104     case Arrayify:
1105     case ArrayifyToStructure:
1106         read(JSCell_structureID);
1107         read(JSCell_indexingType);
1108         read(JSObject_butterfly);
1109         write(JSCell_structureID);
1110         write(JSCell_indexingType);
1111         write(JSObject_butterfly);
1112         write(Watchpoint_fire);
1113         return;
1114         
1115     case GetIndexedPropertyStorage:
1116         if (node->arrayMode().type() == Array::String) {
1117             def(PureValue(node, node->arrayMode().asWord()));
1118             return;
1119         }
1120         read(MiscFields);
1121         def(HeapLocation(IndexedPropertyStorageLoc, MiscFields, node->child1()), LazyNode(node));
1122         return;
1123         
1124     case GetTypedArrayByteOffset:
1125         read(MiscFields);
1126         def(HeapLocation(TypedArrayByteOffsetLoc, MiscFields, node->child1()), LazyNode(node));
1127         return;
1128
1129     case GetPrototypeOf: {
1130         switch (node->child1().useKind()) {
1131         case ArrayUse:
1132         case FunctionUse:
1133         case FinalObjectUse:
1134             read(JSCell_structureID);
1135             read(JSObject_butterfly);
1136             read(NamedProperties); // Poly proto could load prototype from its slot.
1137             def(HeapLocation(PrototypeLoc, NamedProperties, node->child1()), LazyNode(node));
1138             return;
1139         default:
1140             read(World);
1141             write(Heap);
1142             return;
1143         }
1144     }
1145         
1146     case GetByOffset:
1147     case GetGetterSetterByOffset: {
1148         unsigned identifierNumber = node->storageAccessData().identifierNumber;
1149         AbstractHeap heap(NamedProperties, identifierNumber);
1150         read(heap);
1151         def(HeapLocation(NamedPropertyLoc, heap, node->child2()), LazyNode(node));
1152         return;
1153     }
1154
1155     case TryGetById: {
1156         read(Heap);
1157         return;
1158     }
1159
1160     case MultiGetByOffset: {
1161         read(JSCell_structureID);
1162         read(JSObject_butterfly);
1163         AbstractHeap heap(NamedProperties, node->multiGetByOffsetData().identifierNumber);
1164         read(heap);
1165         // FIXME: We cannot def() for MultiGetByOffset because CSE is not smart enough to decay it
1166         // to a CheckStructure.
1167         // https://bugs.webkit.org/show_bug.cgi?id=159859
1168         return;
1169     }
1170         
1171     case MultiPutByOffset: {
1172         read(JSCell_structureID);
1173         read(JSObject_butterfly);
1174         AbstractHeap heap(NamedProperties, node->multiPutByOffsetData().identifierNumber);
1175         write(heap);
1176         if (node->multiPutByOffsetData().writesStructures())
1177             write(JSCell_structureID);
1178         if (node->multiPutByOffsetData().reallocatesStorage())
1179             write(JSObject_butterfly);
1180         def(HeapLocation(NamedPropertyLoc, heap, node->child1()), LazyNode(node->child2().node()));
1181         return;
1182     }
1183         
1184     case PutByOffset: {
1185         unsigned identifierNumber = node->storageAccessData().identifierNumber;
1186         AbstractHeap heap(NamedProperties, identifierNumber);
1187         write(heap);
1188         def(HeapLocation(NamedPropertyLoc, heap, node->child2()), LazyNode(node->child3().node()));
1189         return;
1190     }
1191         
1192     case GetArrayLength: {
1193         ArrayMode mode = node->arrayMode();
1194         switch (mode.type()) {
1195         case Array::Undecided:
1196         case Array::Int32:
1197         case Array::Double:
1198         case Array::Contiguous:
1199         case Array::ArrayStorage:
1200         case Array::SlowPutArrayStorage:
1201             read(Butterfly_publicLength);
1202             def(HeapLocation(ArrayLengthLoc, Butterfly_publicLength, node->child1()), LazyNode(node));
1203             return;
1204             
1205         case Array::String:
1206             def(PureValue(node, mode.asWord()));
1207             return;
1208
1209         case Array::DirectArguments:
1210         case Array::ScopedArguments:
1211             read(MiscFields);
1212             def(HeapLocation(ArrayLengthLoc, MiscFields, node->child1()), LazyNode(node));
1213             return;
1214
1215         default:
1216             ASSERT(mode.isSomeTypedArrayView());
1217             read(MiscFields);
1218             def(HeapLocation(ArrayLengthLoc, MiscFields, node->child1()), LazyNode(node));
1219             return;
1220         }
1221     }
1222
1223     case GetVectorLength: {
1224         ArrayMode mode = node->arrayMode();
1225         switch (mode.type()) {
1226         case Array::ArrayStorage:
1227         case Array::SlowPutArrayStorage:
1228             read(Butterfly_vectorLength);
1229             def(HeapLocation(VectorLengthLoc, Butterfly_vectorLength, node->child1()), LazyNode(node));
1230             return;
1231
1232         default:
1233             RELEASE_ASSERT_NOT_REACHED();
1234             return;
1235         }
1236     }
1237         
1238     case GetClosureVar:
1239         read(AbstractHeap(ScopeProperties, node->scopeOffset().offset()));
1240         def(HeapLocation(ClosureVariableLoc, AbstractHeap(ScopeProperties, node->scopeOffset().offset()), node->child1()), LazyNode(node));
1241         return;
1242         
1243     case PutClosureVar:
1244         write(AbstractHeap(ScopeProperties, node->scopeOffset().offset()));
1245         def(HeapLocation(ClosureVariableLoc, AbstractHeap(ScopeProperties, node->scopeOffset().offset()), node->child1()), LazyNode(node->child2().node()));
1246         return;
1247
1248     case GetRegExpObjectLastIndex:
1249         read(RegExpObject_lastIndex);
1250         def(HeapLocation(RegExpObjectLastIndexLoc, RegExpObject_lastIndex, node->child1()), LazyNode(node));
1251         return;
1252
1253     case SetRegExpObjectLastIndex:
1254         write(RegExpObject_lastIndex);
1255         def(HeapLocation(RegExpObjectLastIndexLoc, RegExpObject_lastIndex, node->child1()), LazyNode(node->child2().node()));
1256         return;
1257
1258     case RecordRegExpCachedResult:
1259         write(RegExpState);
1260         return;
1261         
1262     case GetFromArguments: {
1263         AbstractHeap heap(DirectArgumentsProperties, node->capturedArgumentsOffset().offset());
1264         read(heap);
1265         def(HeapLocation(DirectArgumentsLoc, heap, node->child1()), LazyNode(node));
1266         return;
1267     }
1268         
1269     case PutToArguments: {
1270         AbstractHeap heap(DirectArgumentsProperties, node->capturedArgumentsOffset().offset());
1271         write(heap);
1272         def(HeapLocation(DirectArgumentsLoc, heap, node->child1()), LazyNode(node->child2().node()));
1273         return;
1274     }
1275
1276     case GetArgument: {
1277         read(Stack);
1278         // FIXME: It would be trivial to have a def here.
1279         // https://bugs.webkit.org/show_bug.cgi?id=143077
1280         return;
1281     }
1282         
1283     case GetGlobalVar:
1284     case GetGlobalLexicalVariable:
1285         read(AbstractHeap(Absolute, node->variablePointer()));
1286         def(HeapLocation(GlobalVariableLoc, AbstractHeap(Absolute, node->variablePointer())), LazyNode(node));
1287         return;
1288         
1289     case PutGlobalVariable:
1290         write(AbstractHeap(Absolute, node->variablePointer()));
1291         def(HeapLocation(GlobalVariableLoc, AbstractHeap(Absolute, node->variablePointer())), LazyNode(node->child2().node()));
1292         return;
1293
1294     case NewArrayWithSize:
1295     case NewTypedArray:
1296         read(HeapObjectCount);
1297         write(HeapObjectCount);
1298         return;
1299
1300     case NewArrayWithSpread: {
1301         // This also reads from JSFixedArray's data store, but we don't have any way of describing that yet.
1302         read(HeapObjectCount);
1303         for (unsigned i = 0; i < node->numChildren(); i++) {
1304             Node* child = graph.varArgChild(node, i).node();
1305             if (child->op() == PhantomSpread) {
1306                 read(Stack);
1307                 break;
1308             }
1309         }
1310         write(HeapObjectCount);
1311         return;
1312     }
1313
1314     case Spread: {
1315         if (node->child1()->op() == PhantomCreateRest)
1316             read(Stack);
1317
1318         if (node->child1().useKind() == ArrayUse) {
1319             // FIXME: We can probably CSE these together, but we need to construct the right rules
1320             // to prove that nobody writes to child1() in between two Spreads: https://bugs.webkit.org/show_bug.cgi?id=164531
1321             read(HeapObjectCount); 
1322             read(JSCell_indexingType);
1323             read(JSObject_butterfly);
1324             read(Butterfly_publicLength);
1325             read(IndexedDoubleProperties);
1326             read(IndexedInt32Properties);
1327             read(IndexedContiguousProperties);
1328             read(IndexedArrayStorageProperties);
1329
1330             write(HeapObjectCount);
1331             return;
1332         }
1333
1334         read(World);
1335         write(Heap);
1336         return;
1337     }
1338
1339     case NewArray: {
1340         read(HeapObjectCount);
1341         write(HeapObjectCount);
1342
1343         unsigned numElements = node->numChildren();
1344
1345         def(HeapLocation(ArrayLengthLoc, Butterfly_publicLength, node),
1346             LazyNode(graph.freeze(jsNumber(numElements))));
1347
1348         if (!numElements)
1349             return;
1350
1351         AbstractHeap heap;
1352         LocationKind indexedPropertyLoc;
1353         switch (node->indexingType()) {
1354         case ALL_DOUBLE_INDEXING_TYPES:
1355             heap = IndexedDoubleProperties;
1356             indexedPropertyLoc = IndexedPropertyDoubleLoc;
1357             break;
1358
1359         case ALL_INT32_INDEXING_TYPES:
1360             heap = IndexedInt32Properties;
1361             indexedPropertyLoc = IndexedPropertyJSLoc;
1362             break;
1363
1364         case ALL_CONTIGUOUS_INDEXING_TYPES:
1365             heap = IndexedContiguousProperties;
1366             indexedPropertyLoc = IndexedPropertyJSLoc;
1367             break;
1368
1369         default:
1370             return;
1371         }
1372
1373         if (numElements < graph.m_uint32ValuesInUse.size()) {
1374             for (unsigned operandIdx = 0; operandIdx < numElements; ++operandIdx) {
1375                 Edge use = graph.m_varArgChildren[node->firstChild() + operandIdx];
1376                 def(HeapLocation(indexedPropertyLoc, heap, node, LazyNode(graph.freeze(jsNumber(operandIdx)))),
1377                     LazyNode(use.node()));
1378             }
1379         } else {
1380             for (uint32_t operandIdx : graph.m_uint32ValuesInUse) {
1381                 if (operandIdx >= numElements)
1382                     continue;
1383                 Edge use = graph.m_varArgChildren[node->firstChild() + operandIdx];
1384                 // operandIdx comes from graph.m_uint32ValuesInUse and thus is guaranteed to be already frozen
1385                 def(HeapLocation(indexedPropertyLoc, heap, node, LazyNode(graph.freeze(jsNumber(operandIdx)))),
1386                     LazyNode(use.node()));
1387             }
1388         }
1389         return;
1390     }
1391
1392     case NewArrayBuffer: {
1393         read(HeapObjectCount);
1394         write(HeapObjectCount);
1395
1396         JSFixedArray* array = node->castOperand<JSFixedArray*>();
1397         unsigned numElements = array->length();
1398         def(HeapLocation(ArrayLengthLoc, Butterfly_publicLength, node),
1399             LazyNode(graph.freeze(jsNumber(numElements))));
1400
1401         AbstractHeap heap;
1402         LocationKind indexedPropertyLoc;
1403         NodeType op = JSConstant;
1404         switch (node->indexingType()) {
1405         case ALL_DOUBLE_INDEXING_TYPES:
1406             heap = IndexedDoubleProperties;
1407             indexedPropertyLoc = IndexedPropertyDoubleLoc;
1408             op = DoubleConstant;
1409             break;
1410
1411         case ALL_INT32_INDEXING_TYPES:
1412             heap = IndexedInt32Properties;
1413             indexedPropertyLoc = IndexedPropertyJSLoc;
1414             break;
1415
1416         case ALL_CONTIGUOUS_INDEXING_TYPES:
1417             heap = IndexedContiguousProperties;
1418             indexedPropertyLoc = IndexedPropertyJSLoc;
1419             break;
1420
1421         default:
1422             return;
1423         }
1424
1425         if (numElements < graph.m_uint32ValuesInUse.size()) {
1426             for (unsigned index = 0; index < numElements; ++index) {
1427                 def(HeapLocation(indexedPropertyLoc, heap, node, LazyNode(graph.freeze(jsNumber(index)))),
1428                     LazyNode(graph.freeze(array->get(index)), op));
1429             }
1430         } else {
1431             Vector<uint32_t> possibleIndices;
1432             for (uint32_t index : graph.m_uint32ValuesInUse) {
1433                 if (index >= numElements)
1434                     continue;
1435                 possibleIndices.append(index);
1436             }
1437             for (uint32_t index : possibleIndices) {
1438                 def(HeapLocation(indexedPropertyLoc, heap, node, LazyNode(graph.freeze(jsNumber(index)))),
1439                     LazyNode(graph.freeze(array->get(index)), op));
1440             }
1441         }
1442         return;
1443     }
1444
1445     case CreateRest: {
1446         if (!graph.isWatchingHavingABadTimeWatchpoint(node)) {
1447             // This means we're already having a bad time.
1448             read(World);
1449             write(Heap);
1450             return;
1451         }
1452         read(Stack);
1453         read(HeapObjectCount);
1454         write(HeapObjectCount);
1455         return;
1456     }
1457
1458     case NewObject:
1459     case NewRegexp:
1460     case NewStringObject:
1461     case PhantomNewObject:
1462     case MaterializeNewObject:
1463     case PhantomNewFunction:
1464     case PhantomNewGeneratorFunction:
1465     case PhantomNewAsyncFunction:
1466     case PhantomNewAsyncGeneratorFunction:
1467     case PhantomCreateActivation:
1468     case MaterializeCreateActivation:
1469         read(HeapObjectCount);
1470         write(HeapObjectCount);
1471         return;
1472
1473     case NewFunction:
1474     case NewGeneratorFunction:
1475     case NewAsyncGeneratorFunction:
1476     case NewAsyncFunction:
1477         if (node->castOperand<FunctionExecutable*>()->singletonFunction()->isStillValid())
1478             write(Watchpoint_fire);
1479         read(HeapObjectCount);
1480         write(HeapObjectCount);
1481         return;
1482
1483     case RegExpExec:
1484     case RegExpTest:
1485         if (node->child2().useKind() == RegExpObjectUse
1486             && node->child3().useKind() == StringUse) {
1487             read(RegExpState);
1488             read(RegExpObject_lastIndex);
1489             write(RegExpState);
1490             write(RegExpObject_lastIndex);
1491             return;
1492         }
1493         read(World);
1494         write(Heap);
1495         return;
1496
1497     case StringReplace:
1498     case StringReplaceRegExp:
1499         if (node->child1().useKind() == StringUse
1500             && node->child2().useKind() == RegExpObjectUse
1501             && node->child3().useKind() == StringUse) {
1502             read(RegExpState);
1503             read(RegExpObject_lastIndex);
1504             write(RegExpState);
1505             write(RegExpObject_lastIndex);
1506             return;
1507         }
1508         read(World);
1509         write(Heap);
1510         return;
1511
1512     case StringCharAt:
1513         if (node->arrayMode().isOutOfBounds()) {
1514             read(World);
1515             write(Heap);
1516             return;
1517         }
1518         def(PureValue(node));
1519         return;
1520
1521     case CompareBelow:
1522     case CompareBelowEq:
1523         def(PureValue(node));
1524         return;
1525         
1526     case CompareEq:
1527     case CompareLess:
1528     case CompareLessEq:
1529     case CompareGreater:
1530     case CompareGreaterEq:
1531         if (node->isBinaryUseKind(StringUse)) {
1532             read(HeapObjectCount);
1533             write(HeapObjectCount);
1534             return;
1535         }
1536         if (!node->isBinaryUseKind(UntypedUse)) {
1537             def(PureValue(node));
1538             return;
1539         }
1540         read(World);
1541         write(Heap);
1542         return;
1543
1544     case ToNumber: {
1545         read(World);
1546         write(Heap);
1547         return;
1548     }
1549         
1550     case ToString:
1551     case CallStringConstructor:
1552         switch (node->child1().useKind()) {
1553         case StringObjectUse:
1554         case StringOrStringObjectUse:
1555             // These don't def a pure value, unfortunately. I'll avoid load-eliminating these for
1556             // now.
1557             return;
1558             
1559         case CellUse:
1560         case UntypedUse:
1561             read(World);
1562             write(Heap);
1563             return;
1564
1565         case Int32Use:
1566         case Int52RepUse:
1567         case DoubleRepUse:
1568         case NotCellUse:
1569             def(PureValue(node));
1570             return;
1571             
1572         default:
1573             RELEASE_ASSERT_NOT_REACHED();
1574             return;
1575         }
1576         
1577     case CountExecution:
1578     case SuperSamplerBegin:
1579     case SuperSamplerEnd:
1580         read(InternalState);
1581         write(InternalState);
1582         return;
1583         
1584     case LogShadowChickenPrologue:
1585     case LogShadowChickenTail:
1586         write(SideState);
1587         return;
1588
1589     case MapHash:
1590         def(PureValue(node));
1591         return;
1592
1593     case NormalizeMapKey:
1594         def(PureValue(node));
1595         return;
1596
1597     case GetMapBucket: {
1598         Edge& mapEdge = node->child1();
1599         Edge& keyEdge = node->child2();
1600         AbstractHeapKind heap = (mapEdge.useKind() == MapObjectUse) ? JSMapFields : JSSetFields;
1601         read(heap);
1602         def(HeapLocation(MapBucketLoc, heap, mapEdge, keyEdge), LazyNode(node));
1603         return;
1604     }
1605
1606     case GetMapBucketHead: {
1607         Edge& mapEdge = node->child1();
1608         AbstractHeapKind heap = (mapEdge.useKind() == MapObjectUse) ? JSMapFields : JSSetFields;
1609         read(heap);
1610         def(HeapLocation(MapBucketHeadLoc, heap, mapEdge), LazyNode(node));
1611         return;
1612     }
1613
1614     case GetMapBucketNext: {
1615         AbstractHeapKind heap = (node->bucketOwnerType() == BucketOwnerType::Map) ? JSMapFields : JSSetFields;
1616         read(heap);
1617         Edge& bucketEdge = node->child1();
1618         def(HeapLocation(MapBucketNextLoc, heap, bucketEdge), LazyNode(node));
1619         return;
1620     }
1621
1622     case LoadKeyFromMapBucket: {
1623         AbstractHeapKind heap = (node->bucketOwnerType() == BucketOwnerType::Map) ? JSMapFields : JSSetFields;
1624         read(heap);
1625         Edge& bucketEdge = node->child1();
1626         def(HeapLocation(MapBucketKeyLoc, heap, bucketEdge), LazyNode(node));
1627         return;
1628     }
1629
1630     case LoadValueFromMapBucket: {
1631         AbstractHeapKind heap = (node->bucketOwnerType() == BucketOwnerType::Map) ? JSMapFields : JSSetFields;
1632         read(heap);
1633         Edge& bucketEdge = node->child1();
1634         def(HeapLocation(MapBucketValueLoc, heap, bucketEdge), LazyNode(node));
1635         return;
1636     }
1637
1638     case WeakMapGet: {
1639         Edge& mapEdge = node->child1();
1640         Edge& keyEdge = node->child2();
1641         AbstractHeapKind heap = (mapEdge.useKind() == WeakMapObjectUse) ? JSWeakMapFields : JSWeakSetFields;
1642         read(heap);
1643         def(HeapLocation(WeakMapGetLoc, heap, mapEdge, keyEdge), LazyNode(node));
1644         return;
1645     }
1646
1647     case SetAdd: {
1648         // FIXME: Define defs for them to participate in CSE.
1649         // https://bugs.webkit.org/show_bug.cgi?id=179911
1650         write(JSSetFields);
1651         return;
1652     }
1653
1654     case MapSet: {
1655         // FIXME: Define defs for them to participate in CSE.
1656         // https://bugs.webkit.org/show_bug.cgi?id=179911
1657         write(JSMapFields);
1658         return;
1659     }
1660
1661     case ExtractValueFromWeakMapGet:
1662         def(PureValue(node));
1663         return;
1664
1665     case StringSlice:
1666         def(PureValue(node));
1667         return;
1668
1669     case ToLowerCase:
1670         def(PureValue(node));
1671         return;
1672
1673     case NumberToStringWithRadix:
1674         // If the radix is invalid, NumberToStringWithRadix can throw an error.
1675         read(World);
1676         write(Heap);
1677         return;
1678
1679     case NumberToStringWithValidRadixConstant:
1680         def(PureValue(node, node->validRadixConstant()));
1681         return;
1682         
1683     case LastNodeType:
1684         RELEASE_ASSERT_NOT_REACHED();
1685         return;
1686     }
1687     
1688     DFG_CRASH(graph, node, toCString("Unrecognized node type: ", Graph::opName(node->op())).data());
1689 }
1690
1691 class NoOpClobberize {
1692 public:
1693     NoOpClobberize() { }
1694     template<typename... T>
1695     void operator()(T...) const { }
1696 };
1697
1698 class CheckClobberize {
1699 public:
1700     CheckClobberize()
1701         : m_result(false)
1702     {
1703     }
1704     
1705     template<typename... T>
1706     void operator()(T...) const { m_result = true; }
1707     
1708     bool result() const { return m_result; }
1709     
1710 private:
1711     mutable bool m_result;
1712 };
1713
1714 bool doesWrites(Graph&, Node*);
1715
1716 class AbstractHeapOverlaps {
1717 public:
1718     AbstractHeapOverlaps(AbstractHeap heap)
1719         : m_heap(heap)
1720         , m_result(false)
1721     {
1722     }
1723     
1724     void operator()(AbstractHeap otherHeap) const
1725     {
1726         if (m_result)
1727             return;
1728         m_result = m_heap.overlaps(otherHeap);
1729     }
1730     
1731     bool result() const { return m_result; }
1732
1733 private:
1734     AbstractHeap m_heap;
1735     mutable bool m_result;
1736 };
1737
1738 bool accessesOverlap(Graph&, Node*, AbstractHeap);
1739 bool writesOverlap(Graph&, Node*, AbstractHeap);
1740
1741 bool clobbersHeap(Graph&, Node*);
1742
1743 // We would have used bind() for these, but because of the overlaoding that we are doing,
1744 // it's quite a bit of clearer to just write this out the traditional way.
1745
1746 template<typename T>
1747 class ReadMethodClobberize {
1748 public:
1749     ReadMethodClobberize(T& value)
1750         : m_value(value)
1751     {
1752     }
1753     
1754     void operator()(AbstractHeap heap) const
1755     {
1756         m_value.read(heap);
1757     }
1758 private:
1759     T& m_value;
1760 };
1761
1762 template<typename T>
1763 class WriteMethodClobberize {
1764 public:
1765     WriteMethodClobberize(T& value)
1766         : m_value(value)
1767     {
1768     }
1769     
1770     void operator()(AbstractHeap heap) const
1771     {
1772         m_value.write(heap);
1773     }
1774 private:
1775     T& m_value;
1776 };
1777
1778 template<typename T>
1779 class DefMethodClobberize {
1780 public:
1781     DefMethodClobberize(T& value)
1782         : m_value(value)
1783     {
1784     }
1785     
1786     void operator()(PureValue value) const
1787     {
1788         m_value.def(value);
1789     }
1790     
1791     void operator()(HeapLocation location, LazyNode node) const
1792     {
1793         m_value.def(location, node);
1794     }
1795
1796 private:
1797     T& m_value;
1798 };
1799
1800 template<typename Adaptor>
1801 void clobberize(Graph& graph, Node* node, Adaptor& adaptor)
1802 {
1803     ReadMethodClobberize<Adaptor> read(adaptor);
1804     WriteMethodClobberize<Adaptor> write(adaptor);
1805     DefMethodClobberize<Adaptor> def(adaptor);
1806     clobberize(graph, node, read, write, def);
1807 }
1808
1809 } } // namespace JSC::DFG
1810
1811 #endif // ENABLE(DFG_JIT)