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