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