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