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