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