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