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