REGRESSION(r222563): removed DoubleReal type check causes tons of crashes because...
[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 GetByValWithThis:
589     case PutById:
590     case PutByIdWithThis:
591     case PutByValWithThis:
592     case PutByIdFlush:
593     case PutByIdDirect:
594     case PutGetterById:
595     case PutSetterById:
596     case PutGetterSetterById:
597     case PutGetterByVal:
598     case PutSetterByVal:
599     case DefineDataProperty:
600     case DefineAccessorProperty:
601     case DeleteById:
602     case DeleteByVal:
603     case ArrayPush:
604     case ArrayPop:
605     case Call:
606     case DirectCall:
607     case TailCallInlinedCaller:
608     case DirectTailCallInlinedCaller:
609     case Construct:
610     case DirectConstruct:
611     case CallVarargs:
612     case CallForwardVarargs:
613     case TailCallVarargsInlinedCaller:
614     case TailCallForwardVarargsInlinedCaller:
615     case ConstructVarargs:
616     case ConstructForwardVarargs:
617     case ToPrimitive:
618     case In:
619     case HasOwnProperty:
620     case ValueAdd:
621     case SetFunctionName:
622     case GetDynamicVar:
623     case PutDynamicVar:
624     case ResolveScopeForHoistingFuncDeclInEval:
625     case ResolveScope:
626     case ToObject:
627     case HasGenericProperty:
628     case HasStructureProperty:
629     case GetPropertyEnumerator:
630     case GetDirectPname:
631     case InstanceOfCustom:
632     case ToNumber:
633     case NumberToStringWithRadix:
634     case CreateThis:
635         read(World);
636         write(Heap);
637         return;
638
639     case AtomicsAdd:
640     case AtomicsAnd:
641     case AtomicsCompareExchange:
642     case AtomicsExchange:
643     case AtomicsLoad:
644     case AtomicsOr:
645     case AtomicsStore:
646     case AtomicsSub:
647     case AtomicsXor: {
648         unsigned numExtraArgs = numExtraAtomicsArgs(node->op());
649         Edge storageEdge = graph.child(node, 2 + numExtraArgs);
650         if (!storageEdge) {
651             read(World);
652             write(Heap);
653             return;
654         }
655         read(TypedArrayProperties);
656         read(MiscFields);
657         write(TypedArrayProperties);
658         return;
659     }
660
661     case CallEval:
662         ASSERT(!node->origin.semantic.inlineCallFrame);
663         read(AbstractHeap(Stack, graph.m_codeBlock->scopeRegister()));
664         read(AbstractHeap(Stack, virtualRegisterForArgument(0)));
665         read(World);
666         write(Heap);
667         return;
668
669     case Throw:
670     case ThrowStaticError:
671     case TailCall:
672     case DirectTailCall:
673     case TailCallVarargs:
674     case TailCallForwardVarargs:
675         read(World);
676         write(SideState);
677         return;
678         
679     case GetGetter:
680         read(GetterSetter_getter);
681         def(HeapLocation(GetterLoc, GetterSetter_getter, node->child1()), LazyNode(node));
682         return;
683         
684     case GetSetter:
685         read(GetterSetter_setter);
686         def(HeapLocation(SetterLoc, GetterSetter_setter, node->child1()), LazyNode(node));
687         return;
688         
689     case GetCallee:
690         read(AbstractHeap(Stack, CallFrameSlot::callee));
691         def(HeapLocation(StackLoc, AbstractHeap(Stack, CallFrameSlot::callee)), LazyNode(node));
692         return;
693         
694     case GetArgumentCountIncludingThis: {
695         auto heap = AbstractHeap(Stack, remapOperand(node->argumentsInlineCallFrame(), VirtualRegister(CallFrameSlot::argumentCount)));
696         read(heap);
697         def(HeapLocation(StackPayloadLoc, heap), LazyNode(node));
698         return;
699     }
700
701     case SetArgumentCountIncludingThis:
702         write(AbstractHeap(Stack, CallFrameSlot::argumentCount));
703         return;
704
705     case GetRestLength:
706         read(Stack);
707         return;
708         
709     case GetLocal:
710         read(AbstractHeap(Stack, node->local()));
711         def(HeapLocation(StackLoc, AbstractHeap(Stack, node->local())), LazyNode(node));
712         return;
713         
714     case SetLocal:
715         write(AbstractHeap(Stack, node->local()));
716         def(HeapLocation(StackLoc, AbstractHeap(Stack, node->local())), LazyNode(node->child1().node()));
717         return;
718         
719     case GetStack: {
720         AbstractHeap heap(Stack, node->stackAccessData()->local);
721         read(heap);
722         def(HeapLocation(StackLoc, heap), LazyNode(node));
723         return;
724     }
725         
726     case PutStack: {
727         AbstractHeap heap(Stack, node->stackAccessData()->local);
728         write(heap);
729         def(HeapLocation(StackLoc, heap), LazyNode(node->child1().node()));
730         return;
731     }
732         
733     case LoadVarargs: {
734         read(World);
735         write(Heap);
736         LoadVarargsData* data = node->loadVarargsData();
737         write(AbstractHeap(Stack, data->count.offset()));
738         for (unsigned i = data->limit; i--;)
739             write(AbstractHeap(Stack, data->start.offset() + static_cast<int>(i)));
740         return;
741     }
742         
743     case ForwardVarargs: {
744         // We could be way more precise here.
745         read(Stack);
746         
747         LoadVarargsData* data = node->loadVarargsData();
748         write(AbstractHeap(Stack, data->count.offset()));
749         for (unsigned i = data->limit; i--;)
750             write(AbstractHeap(Stack, data->start.offset() + static_cast<int>(i)));
751         return;
752     }
753         
754     case GetByVal: {
755         ArrayMode mode = node->arrayMode();
756         LocationKind indexedPropertyLoc = indexedPropertyLocForResultType(node->result());
757         switch (mode.type()) {
758         case Array::SelectUsingPredictions:
759         case Array::Unprofiled:
760         case Array::SelectUsingArguments:
761             // Assume the worst since we don't have profiling yet.
762             read(World);
763             write(Heap);
764             return;
765             
766         case Array::ForceExit:
767             write(SideState);
768             return;
769             
770         case Array::Generic:
771             read(World);
772             write(Heap);
773             return;
774             
775         case Array::String:
776             if (mode.isOutOfBounds()) {
777                 read(World);
778                 write(Heap);
779                 return;
780             }
781             // This appears to read nothing because it's only reading immutable data.
782             def(PureValue(graph, node, mode.asWord()));
783             return;
784             
785         case Array::DirectArguments:
786             if (mode.isInBounds()) {
787                 read(DirectArgumentsProperties);
788                 def(HeapLocation(indexedPropertyLoc, DirectArgumentsProperties, graph.varArgChild(node, 0), graph.varArgChild(node, 1)), LazyNode(node));
789                 return;
790             }
791             read(World);
792             write(Heap);
793             return;
794             
795         case Array::ScopedArguments:
796             read(ScopeProperties);
797             def(HeapLocation(indexedPropertyLoc, ScopeProperties, graph.varArgChild(node, 0), graph.varArgChild(node, 1)), LazyNode(node));
798             return;
799             
800         case Array::Int32:
801             if (mode.isInBounds()) {
802                 read(Butterfly_publicLength);
803                 read(IndexedInt32Properties);
804                 def(HeapLocation(indexedPropertyLoc, IndexedInt32Properties, graph.varArgChild(node, 0), graph.varArgChild(node, 1)), LazyNode(node));
805                 return;
806             }
807             read(World);
808             write(Heap);
809             return;
810             
811         case Array::Double:
812             if (mode.isInBounds()) {
813                 read(Butterfly_publicLength);
814                 read(IndexedDoubleProperties);
815                 LocationKind kind = mode.isSaneChain() ? IndexedPropertyDoubleSaneChainLoc : IndexedPropertyDoubleLoc;
816                 def(HeapLocation(kind, IndexedDoubleProperties, 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::Contiguous:
824             if (mode.isInBounds()) {
825                 read(Butterfly_publicLength);
826                 read(IndexedContiguousProperties);
827                 def(HeapLocation(indexedPropertyLoc, IndexedContiguousProperties, 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::Undecided:
835             def(PureValue(graph, node));
836             return;
837             
838         case Array::ArrayStorage:
839         case Array::SlowPutArrayStorage:
840             if (mode.isInBounds()) {
841                 read(Butterfly_vectorLength);
842                 read(IndexedArrayStorageProperties);
843                 return;
844             }
845             read(World);
846             write(Heap);
847             return;
848             
849         case Array::Int8Array:
850         case Array::Int16Array:
851         case Array::Int32Array:
852         case Array::Uint8Array:
853         case Array::Uint8ClampedArray:
854         case Array::Uint16Array:
855         case Array::Uint32Array:
856         case Array::Float32Array:
857         case Array::Float64Array:
858             read(TypedArrayProperties);
859             read(MiscFields);
860             def(HeapLocation(indexedPropertyLoc, TypedArrayProperties, graph.varArgChild(node, 0), graph.varArgChild(node, 1)), LazyNode(node));
861             return;
862         // We should not get an AnyTypedArray in a GetByVal as AnyTypedArray is only created from intrinsics, which
863         // are only added from Inline Caching a GetById.
864         case Array::AnyTypedArray:
865             DFG_CRASH(graph, node, "impossible array mode for get");
866             return;
867         }
868         RELEASE_ASSERT_NOT_REACHED();
869         return;
870     }
871         
872     case GetMyArgumentByVal:
873     case GetMyArgumentByValOutOfBounds: {
874         read(Stack);
875         // FIXME: It would be trivial to have a def here.
876         // https://bugs.webkit.org/show_bug.cgi?id=143077
877         return;
878     }
879
880     case PutByValDirect:
881     case PutByVal:
882     case PutByValAlias: {
883         ArrayMode mode = node->arrayMode();
884         Node* base = graph.varArgChild(node, 0).node();
885         Node* index = graph.varArgChild(node, 1).node();
886         Node* value = graph.varArgChild(node, 2).node();
887         LocationKind indexedPropertyLoc = indexedPropertyLocForResultType(node->result());
888
889         switch (mode.modeForPut().type()) {
890         case Array::SelectUsingPredictions:
891         case Array::SelectUsingArguments:
892         case Array::Unprofiled:
893         case Array::Undecided:
894             // Assume the worst since we don't have profiling yet.
895             read(World);
896             write(Heap);
897             return;
898             
899         case Array::ForceExit:
900             write(SideState);
901             return;
902             
903         case Array::Generic:
904             read(World);
905             write(Heap);
906             return;
907             
908         case Array::Int32:
909             if (node->arrayMode().isOutOfBounds()) {
910                 read(World);
911                 write(Heap);
912                 return;
913             }
914             read(Butterfly_publicLength);
915             read(Butterfly_vectorLength);
916             read(IndexedInt32Properties);
917             write(IndexedInt32Properties);
918             if (node->arrayMode().mayStoreToHole())
919                 write(Butterfly_publicLength);
920             def(HeapLocation(indexedPropertyLoc, IndexedInt32Properties, base, index), LazyNode(value));
921             return;
922             
923         case Array::Double:
924             if (node->arrayMode().isOutOfBounds()) {
925                 read(World);
926                 write(Heap);
927                 return;
928             }
929             read(Butterfly_publicLength);
930             read(Butterfly_vectorLength);
931             read(IndexedDoubleProperties);
932             write(IndexedDoubleProperties);
933             if (node->arrayMode().mayStoreToHole())
934                 write(Butterfly_publicLength);
935             def(HeapLocation(IndexedPropertyDoubleLoc, IndexedDoubleProperties, base, index), LazyNode(value));
936             def(HeapLocation(IndexedPropertyDoubleSaneChainLoc, IndexedDoubleProperties, base, index), LazyNode(value));
937             return;
938             
939         case Array::Contiguous:
940             if (node->arrayMode().isOutOfBounds()) {
941                 read(World);
942                 write(Heap);
943                 return;
944             }
945             read(Butterfly_publicLength);
946             read(Butterfly_vectorLength);
947             read(IndexedContiguousProperties);
948             write(IndexedContiguousProperties);
949             if (node->arrayMode().mayStoreToHole())
950                 write(Butterfly_publicLength);
951             def(HeapLocation(indexedPropertyLoc, IndexedContiguousProperties, base, index), LazyNode(value));
952             return;
953             
954         case Array::ArrayStorage:
955         case Array::SlowPutArrayStorage:
956             // Give up on life for now.
957             read(World);
958             write(Heap);
959             return;
960
961         case Array::Int8Array:
962         case Array::Int16Array:
963         case Array::Int32Array:
964         case Array::Uint8Array:
965         case Array::Uint8ClampedArray:
966         case Array::Uint16Array:
967         case Array::Uint32Array:
968         case Array::Float32Array:
969         case Array::Float64Array:
970             read(MiscFields);
971             write(TypedArrayProperties);
972             // FIXME: We can't def() anything here because these operations truncate their inputs.
973             // https://bugs.webkit.org/show_bug.cgi?id=134737
974             return;
975         case Array::AnyTypedArray:
976         case Array::String:
977         case Array::DirectArguments:
978         case Array::ScopedArguments:
979             DFG_CRASH(graph, node, "impossible array mode for put");
980             return;
981         }
982         RELEASE_ASSERT_NOT_REACHED();
983         return;
984     }
985         
986     case CheckStructureOrEmpty:
987     case CheckStructure:
988         read(JSCell_structureID);
989         return;
990
991     case CheckArray:
992         read(JSCell_indexingType);
993         read(JSCell_typeInfoType);
994         read(JSCell_structureID);
995         return;
996
997     case CheckTypeInfoFlags:
998         read(JSCell_typeInfoFlags);
999         def(HeapLocation(CheckTypeInfoFlagsLoc, JSCell_typeInfoFlags, node->child1()), LazyNode(node));
1000         return;
1001
1002     case ParseInt:
1003         // Note: We would have eliminated a ParseInt that has just a single child as an Int32Use inside fixup.
1004         if (node->child1().useKind() == StringUse && (!node->child2() || node->child2().useKind() == Int32Use)) {
1005             def(PureValue(node));
1006             return;
1007         }
1008
1009         read(World);
1010         write(Heap);
1011         return;
1012
1013     case OverridesHasInstance:
1014         read(JSCell_typeInfoFlags);
1015         def(HeapLocation(OverridesHasInstanceLoc, JSCell_typeInfoFlags, node->child1()), LazyNode(node));
1016         return;
1017
1018     case InstanceOf:
1019         read(JSCell_structureID);
1020         def(HeapLocation(InstanceOfLoc, JSCell_structureID, node->child1(), node->child2()), LazyNode(node));
1021         return;
1022
1023     case PutStructure:
1024         read(JSObject_butterfly);
1025         write(JSCell_structureID);
1026         write(JSCell_typeInfoType);
1027         write(JSCell_typeInfoFlags);
1028         write(JSCell_indexingType);
1029         return;
1030         
1031     case AllocatePropertyStorage:
1032     case ReallocatePropertyStorage:
1033         read(HeapObjectCount);
1034         write(HeapObjectCount);
1035         return;
1036         
1037     case NukeStructureAndSetButterfly:
1038         write(JSObject_butterfly);
1039         write(JSCell_structureID);
1040         def(HeapLocation(ButterflyLoc, JSObject_butterfly, node->child1()), LazyNode(node->child2().node()));
1041         return;
1042         
1043     case GetButterfly:
1044         read(JSObject_butterfly);
1045         def(HeapLocation(ButterflyLoc, JSObject_butterfly, node->child1()), LazyNode(node));
1046         return;
1047
1048     case CheckSubClass:
1049         def(PureValue(node, node->classInfo()));
1050         return;
1051
1052     case CallDOMGetter: {
1053         DOMJIT::CallDOMGetterSnippet* snippet = node->callDOMGetterData()->snippet;
1054         if (!snippet) {
1055             read(World);
1056             write(Heap);
1057             return;
1058         }
1059         DOMJIT::Effect effect = snippet->effect;
1060         if (effect.reads) {
1061             if (effect.reads == DOMJIT::HeapRange::top())
1062                 read(World);
1063             else
1064                 read(AbstractHeap(DOMState, effect.reads.rawRepresentation()));
1065         }
1066         if (effect.writes) {
1067             if (effect.writes == DOMJIT::HeapRange::top())
1068                 write(Heap);
1069             else
1070                 write(AbstractHeap(DOMState, effect.writes.rawRepresentation()));
1071         }
1072         if (effect.def != DOMJIT::HeapRange::top()) {
1073             DOMJIT::HeapRange range = effect.def;
1074             if (range == DOMJIT::HeapRange::none())
1075                 def(PureValue(node, bitwise_cast<uintptr_t>(node->callDOMGetterData()->customAccessorGetter)));
1076             else {
1077                 // Def with heap location. We do not include "GlobalObject" for that since this information is included in the base node.
1078                 // We only see the DOMJIT getter here. So just including "base" is ok.
1079                 def(HeapLocation(DOMStateLoc, AbstractHeap(DOMState, range.rawRepresentation()), node->child1()), LazyNode(node));
1080             }
1081         }
1082         return;
1083     }
1084
1085     case CallDOM: {
1086         const DOMJIT::Signature* signature = node->signature();
1087         DOMJIT::Effect effect = signature->effect;
1088         if (effect.reads) {
1089             if (effect.reads == DOMJIT::HeapRange::top())
1090                 read(World);
1091             else
1092                 read(AbstractHeap(DOMState, effect.reads.rawRepresentation()));
1093         }
1094         if (effect.writes) {
1095             if (effect.writes == DOMJIT::HeapRange::top())
1096                 write(Heap);
1097             else
1098                 write(AbstractHeap(DOMState, effect.writes.rawRepresentation()));
1099         }
1100         ASSERT_WITH_MESSAGE(effect.def == DOMJIT::HeapRange::top(), "Currently, we do not accept any def for CallDOM.");
1101         return;
1102     }
1103
1104     case Arrayify:
1105     case ArrayifyToStructure:
1106         read(JSCell_structureID);
1107         read(JSCell_indexingType);
1108         read(JSObject_butterfly);
1109         write(JSCell_structureID);
1110         write(JSCell_indexingType);
1111         write(JSObject_butterfly);
1112         write(JSObject_butterflyMask);
1113         write(Watchpoint_fire);
1114         return;
1115         
1116     case GetIndexedPropertyStorage:
1117         if (node->arrayMode().type() == Array::String) {
1118             def(PureValue(node, node->arrayMode().asWord()));
1119             return;
1120         }
1121         read(MiscFields);
1122         def(HeapLocation(IndexedPropertyStorageLoc, MiscFields, node->child1()), LazyNode(node));
1123         return;
1124         
1125     case GetTypedArrayByteOffset:
1126         read(MiscFields);
1127         def(HeapLocation(TypedArrayByteOffsetLoc, MiscFields, node->child1()), LazyNode(node));
1128         return;
1129
1130     case GetPrototypeOf: {
1131         switch (node->child1().useKind()) {
1132         case ArrayUse:
1133         case FunctionUse:
1134         case FinalObjectUse:
1135             read(JSCell_structureID);
1136             read(JSObject_butterfly);
1137             read(NamedProperties); // Poly proto could load prototype from its slot.
1138             def(HeapLocation(PrototypeLoc, NamedProperties, node->child1()), LazyNode(node));
1139             return;
1140         default:
1141             read(World);
1142             write(Heap);
1143             return;
1144         }
1145     }
1146         
1147     case GetByOffset:
1148     case GetGetterSetterByOffset: {
1149         unsigned identifierNumber = node->storageAccessData().identifierNumber;
1150         AbstractHeap heap(NamedProperties, identifierNumber);
1151         read(heap);
1152         def(HeapLocation(NamedPropertyLoc, heap, node->child2()), LazyNode(node));
1153         return;
1154     }
1155
1156     case TryGetById: {
1157         read(Heap);
1158         return;
1159     }
1160
1161     case MultiGetByOffset: {
1162         read(JSCell_structureID);
1163         read(JSObject_butterfly);
1164         read(JSObject_butterflyMask);
1165         AbstractHeap heap(NamedProperties, node->multiGetByOffsetData().identifierNumber);
1166         read(heap);
1167         // FIXME: We cannot def() for MultiGetByOffset because CSE is not smart enough to decay it
1168         // to a CheckStructure.
1169         // https://bugs.webkit.org/show_bug.cgi?id=159859
1170         return;
1171     }
1172         
1173     case MultiPutByOffset: {
1174         read(JSCell_structureID);
1175         read(JSObject_butterfly);
1176         AbstractHeap heap(NamedProperties, node->multiPutByOffsetData().identifierNumber);
1177         write(heap);
1178         if (node->multiPutByOffsetData().writesStructures())
1179             write(JSCell_structureID);
1180         if (node->multiPutByOffsetData().reallocatesStorage())
1181             write(JSObject_butterfly);
1182         def(HeapLocation(NamedPropertyLoc, heap, node->child1()), LazyNode(node->child2().node()));
1183         return;
1184     }
1185         
1186     case PutByOffset: {
1187         unsigned identifierNumber = node->storageAccessData().identifierNumber;
1188         AbstractHeap heap(NamedProperties, identifierNumber);
1189         write(heap);
1190         def(HeapLocation(NamedPropertyLoc, heap, node->child2()), LazyNode(node->child3().node()));
1191         return;
1192     }
1193         
1194     case GetArrayLength: {
1195         ArrayMode mode = node->arrayMode();
1196         switch (mode.type()) {
1197         case Array::Undecided:
1198         case Array::Int32:
1199         case Array::Double:
1200         case Array::Contiguous:
1201         case Array::ArrayStorage:
1202         case Array::SlowPutArrayStorage:
1203             read(Butterfly_publicLength);
1204             def(HeapLocation(ArrayLengthLoc, Butterfly_publicLength, node->child1()), LazyNode(node));
1205             return;
1206             
1207         case Array::String:
1208             def(PureValue(node, mode.asWord()));
1209             return;
1210
1211         case Array::DirectArguments:
1212         case Array::ScopedArguments:
1213             read(MiscFields);
1214             def(HeapLocation(ArrayLengthLoc, MiscFields, node->child1()), LazyNode(node));
1215             return;
1216
1217         default:
1218             ASSERT(mode.isSomeTypedArrayView());
1219             read(MiscFields);
1220             def(HeapLocation(ArrayLengthLoc, MiscFields, node->child1()), LazyNode(node));
1221             return;
1222         }
1223     }
1224
1225     case GetVectorLength: {
1226         ArrayMode mode = node->arrayMode();
1227         switch (mode.type()) {
1228         case Array::ArrayStorage:
1229         case Array::SlowPutArrayStorage:
1230             read(Butterfly_vectorLength);
1231             def(HeapLocation(VectorLengthLoc, Butterfly_vectorLength, node->child1()), LazyNode(node));
1232             return;
1233
1234         default:
1235             RELEASE_ASSERT_NOT_REACHED();
1236             return;
1237         }
1238     }
1239         
1240     case GetClosureVar:
1241         read(AbstractHeap(ScopeProperties, node->scopeOffset().offset()));
1242         def(HeapLocation(ClosureVariableLoc, AbstractHeap(ScopeProperties, node->scopeOffset().offset()), node->child1()), LazyNode(node));
1243         return;
1244         
1245     case PutClosureVar:
1246         write(AbstractHeap(ScopeProperties, node->scopeOffset().offset()));
1247         def(HeapLocation(ClosureVariableLoc, AbstractHeap(ScopeProperties, node->scopeOffset().offset()), node->child1()), LazyNode(node->child2().node()));
1248         return;
1249
1250     case GetRegExpObjectLastIndex:
1251         read(RegExpObject_lastIndex);
1252         def(HeapLocation(RegExpObjectLastIndexLoc, RegExpObject_lastIndex, node->child1()), LazyNode(node));
1253         return;
1254
1255     case SetRegExpObjectLastIndex:
1256         write(RegExpObject_lastIndex);
1257         def(HeapLocation(RegExpObjectLastIndexLoc, RegExpObject_lastIndex, node->child1()), LazyNode(node->child2().node()));
1258         return;
1259
1260     case RecordRegExpCachedResult:
1261         write(RegExpState);
1262         return;
1263         
1264     case GetFromArguments: {
1265         AbstractHeap heap(DirectArgumentsProperties, node->capturedArgumentsOffset().offset());
1266         read(heap);
1267         def(HeapLocation(DirectArgumentsLoc, heap, node->child1()), LazyNode(node));
1268         return;
1269     }
1270         
1271     case PutToArguments: {
1272         AbstractHeap heap(DirectArgumentsProperties, node->capturedArgumentsOffset().offset());
1273         write(heap);
1274         def(HeapLocation(DirectArgumentsLoc, heap, node->child1()), LazyNode(node->child2().node()));
1275         return;
1276     }
1277
1278     case GetArgument: {
1279         read(Stack);
1280         // FIXME: It would be trivial to have a def here.
1281         // https://bugs.webkit.org/show_bug.cgi?id=143077
1282         return;
1283     }
1284         
1285     case GetGlobalVar:
1286     case GetGlobalLexicalVariable:
1287         read(AbstractHeap(Absolute, node->variablePointer()));
1288         def(HeapLocation(GlobalVariableLoc, AbstractHeap(Absolute, node->variablePointer())), LazyNode(node));
1289         return;
1290         
1291     case PutGlobalVariable:
1292         write(AbstractHeap(Absolute, node->variablePointer()));
1293         def(HeapLocation(GlobalVariableLoc, AbstractHeap(Absolute, node->variablePointer())), LazyNode(node->child2().node()));
1294         return;
1295
1296     case NewArrayWithSize:
1297     case NewTypedArray:
1298         read(HeapObjectCount);
1299         write(HeapObjectCount);
1300         return;
1301
1302     case NewArrayWithSpread: {
1303         // This also reads from JSFixedArray's data store, but we don't have any way of describing that yet.
1304         read(HeapObjectCount);
1305         for (unsigned i = 0; i < node->numChildren(); i++) {
1306             Node* child = graph.varArgChild(node, i).node();
1307             if (child->op() == PhantomSpread) {
1308                 read(Stack);
1309                 break;
1310             }
1311         }
1312         write(HeapObjectCount);
1313         return;
1314     }
1315
1316     case Spread: {
1317         if (node->child1()->op() == PhantomNewArrayBuffer) {
1318             read(MiscFields);
1319             return;
1320         }
1321
1322         if (node->child1()->op() == PhantomCreateRest) {
1323             read(Stack);
1324             write(HeapObjectCount);
1325             return;
1326         }
1327
1328         read(World);
1329         write(Heap);
1330         return;
1331     }
1332
1333     case NewArray: {
1334         read(HeapObjectCount);
1335         write(HeapObjectCount);
1336
1337         unsigned numElements = node->numChildren();
1338
1339         def(HeapLocation(ArrayLengthLoc, Butterfly_publicLength, node),
1340             LazyNode(graph.freeze(jsNumber(numElements))));
1341
1342         if (!numElements)
1343             return;
1344
1345         AbstractHeap heap;
1346         LocationKind indexedPropertyLoc;
1347         switch (node->indexingType()) {
1348         case ALL_DOUBLE_INDEXING_TYPES:
1349             heap = IndexedDoubleProperties;
1350             indexedPropertyLoc = IndexedPropertyDoubleLoc;
1351             break;
1352
1353         case ALL_INT32_INDEXING_TYPES:
1354             heap = IndexedInt32Properties;
1355             indexedPropertyLoc = IndexedPropertyJSLoc;
1356             break;
1357
1358         case ALL_CONTIGUOUS_INDEXING_TYPES:
1359             heap = IndexedContiguousProperties;
1360             indexedPropertyLoc = IndexedPropertyJSLoc;
1361             break;
1362
1363         default:
1364             return;
1365         }
1366
1367         if (numElements < graph.m_uint32ValuesInUse.size()) {
1368             for (unsigned operandIdx = 0; operandIdx < numElements; ++operandIdx) {
1369                 Edge use = graph.m_varArgChildren[node->firstChild() + operandIdx];
1370                 def(HeapLocation(indexedPropertyLoc, heap, node, LazyNode(graph.freeze(jsNumber(operandIdx)))),
1371                     LazyNode(use.node()));
1372             }
1373         } else {
1374             for (uint32_t operandIdx : graph.m_uint32ValuesInUse) {
1375                 if (operandIdx >= numElements)
1376                     continue;
1377                 Edge use = graph.m_varArgChildren[node->firstChild() + operandIdx];
1378                 // operandIdx comes from graph.m_uint32ValuesInUse and thus is guaranteed to be already frozen
1379                 def(HeapLocation(indexedPropertyLoc, heap, node, LazyNode(graph.freeze(jsNumber(operandIdx)))),
1380                     LazyNode(use.node()));
1381             }
1382         }
1383         return;
1384     }
1385
1386     case NewArrayBuffer: {
1387         read(HeapObjectCount);
1388         write(HeapObjectCount);
1389
1390         JSFixedArray* array = node->castOperand<JSFixedArray*>();
1391         unsigned numElements = array->length();
1392         def(HeapLocation(ArrayLengthLoc, Butterfly_publicLength, node),
1393             LazyNode(graph.freeze(jsNumber(numElements))));
1394
1395         AbstractHeap heap;
1396         LocationKind indexedPropertyLoc;
1397         NodeType op = JSConstant;
1398         switch (node->indexingType()) {
1399         case ALL_DOUBLE_INDEXING_TYPES:
1400             heap = IndexedDoubleProperties;
1401             indexedPropertyLoc = IndexedPropertyDoubleLoc;
1402             op = DoubleConstant;
1403             break;
1404
1405         case ALL_INT32_INDEXING_TYPES:
1406             heap = IndexedInt32Properties;
1407             indexedPropertyLoc = IndexedPropertyJSLoc;
1408             break;
1409
1410         case ALL_CONTIGUOUS_INDEXING_TYPES:
1411             heap = IndexedContiguousProperties;
1412             indexedPropertyLoc = IndexedPropertyJSLoc;
1413             break;
1414
1415         default:
1416             return;
1417         }
1418
1419         if (numElements < graph.m_uint32ValuesInUse.size()) {
1420             for (unsigned index = 0; index < numElements; ++index) {
1421                 def(HeapLocation(indexedPropertyLoc, heap, node, LazyNode(graph.freeze(jsNumber(index)))),
1422                     LazyNode(graph.freeze(array->get(index)), op));
1423             }
1424         } else {
1425             Vector<uint32_t> possibleIndices;
1426             for (uint32_t index : graph.m_uint32ValuesInUse) {
1427                 if (index >= numElements)
1428                     continue;
1429                 possibleIndices.append(index);
1430             }
1431             for (uint32_t index : possibleIndices) {
1432                 def(HeapLocation(indexedPropertyLoc, heap, node, LazyNode(graph.freeze(jsNumber(index)))),
1433                     LazyNode(graph.freeze(array->get(index)), op));
1434             }
1435         }
1436         return;
1437     }
1438
1439     case CreateRest: {
1440         if (!graph.isWatchingHavingABadTimeWatchpoint(node)) {
1441             // This means we're already having a bad time.
1442             read(World);
1443             write(Heap);
1444             return;
1445         }
1446         read(Stack);
1447         read(HeapObjectCount);
1448         write(HeapObjectCount);
1449         return;
1450     }
1451
1452     case NewObject:
1453     case NewRegexp:
1454     case NewStringObject:
1455     case PhantomNewObject:
1456     case MaterializeNewObject:
1457     case PhantomNewFunction:
1458     case PhantomNewGeneratorFunction:
1459     case PhantomNewAsyncFunction:
1460     case PhantomNewAsyncGeneratorFunction:
1461     case PhantomCreateActivation:
1462     case MaterializeCreateActivation:
1463     case PhantomNewRegexp:
1464         read(HeapObjectCount);
1465         write(HeapObjectCount);
1466         return;
1467
1468     case NewFunction:
1469     case NewGeneratorFunction:
1470     case NewAsyncGeneratorFunction:
1471     case NewAsyncFunction:
1472         if (node->castOperand<FunctionExecutable*>()->singletonFunction()->isStillValid())
1473             write(Watchpoint_fire);
1474         read(HeapObjectCount);
1475         write(HeapObjectCount);
1476         return;
1477
1478     case RegExpExec:
1479     case RegExpTest:
1480     case RegExpMatchFast:
1481         if (node->child2().useKind() == RegExpObjectUse
1482             && node->child3().useKind() == StringUse) {
1483             read(RegExpState);
1484             read(RegExpObject_lastIndex);
1485             write(RegExpState);
1486             write(RegExpObject_lastIndex);
1487             return;
1488         }
1489         read(World);
1490         write(Heap);
1491         return;
1492
1493     case RegExpExecNonGlobalOrSticky:
1494     case RegExpMatchFastGlobal:
1495         read(RegExpState);
1496         write(RegExpState);
1497         return;
1498
1499     case StringReplace:
1500     case StringReplaceRegExp:
1501         if (node->child1().useKind() == StringUse
1502             && node->child2().useKind() == RegExpObjectUse
1503             && node->child3().useKind() == StringUse) {
1504             read(RegExpState);
1505             read(RegExpObject_lastIndex);
1506             write(RegExpState);
1507             write(RegExpObject_lastIndex);
1508             return;
1509         }
1510         read(World);
1511         write(Heap);
1512         return;
1513
1514     case StringCharAt:
1515         if (node->arrayMode().isOutOfBounds()) {
1516             read(World);
1517             write(Heap);
1518             return;
1519         }
1520         def(PureValue(node));
1521         return;
1522
1523     case CompareBelow:
1524     case CompareBelowEq:
1525         def(PureValue(node));
1526         return;
1527         
1528     case CompareEq:
1529     case CompareLess:
1530     case CompareLessEq:
1531     case CompareGreater:
1532     case CompareGreaterEq:
1533         if (node->isBinaryUseKind(StringUse)) {
1534             read(HeapObjectCount);
1535             write(HeapObjectCount);
1536             return;
1537         }
1538
1539         if (node->op() == CompareEq && node->isBinaryUseKind(ObjectUse)) {
1540             def(PureValue(node));
1541             return;
1542         }
1543         if (node->child1().useKind() == UntypedUse || node->child1().useKind() == ObjectUse
1544             || node->child2().useKind() == UntypedUse || node->child2().useKind() == ObjectUse) {
1545             read(World);
1546             write(Heap);
1547             return;
1548         }
1549
1550         def(PureValue(node));
1551         return;
1552
1553     case ToString:
1554     case CallStringConstructor:
1555         switch (node->child1().useKind()) {
1556         case StringObjectUse:
1557         case StringOrStringObjectUse:
1558             // These don't def a pure value, unfortunately. I'll avoid load-eliminating these for
1559             // now.
1560             return;
1561             
1562         case CellUse:
1563         case UntypedUse:
1564             read(World);
1565             write(Heap);
1566             return;
1567
1568         case Int32Use:
1569         case Int52RepUse:
1570         case DoubleRepUse:
1571         case NotCellUse:
1572             def(PureValue(node));
1573             return;
1574             
1575         default:
1576             RELEASE_ASSERT_NOT_REACHED();
1577             return;
1578         }
1579         
1580     case CountExecution:
1581     case SuperSamplerBegin:
1582     case SuperSamplerEnd:
1583         read(InternalState);
1584         write(InternalState);
1585         return;
1586         
1587     case LogShadowChickenPrologue:
1588     case LogShadowChickenTail:
1589         write(SideState);
1590         return;
1591
1592     case MapHash:
1593         def(PureValue(node));
1594         return;
1595
1596     case NormalizeMapKey:
1597         def(PureValue(node));
1598         return;
1599
1600     case GetMapBucket: {
1601         Edge& mapEdge = node->child1();
1602         Edge& keyEdge = node->child2();
1603         AbstractHeapKind heap = (mapEdge.useKind() == MapObjectUse) ? JSMapFields : JSSetFields;
1604         read(heap);
1605         def(HeapLocation(MapBucketLoc, heap, mapEdge, keyEdge), LazyNode(node));
1606         return;
1607     }
1608
1609     case GetMapBucketHead: {
1610         Edge& mapEdge = node->child1();
1611         AbstractHeapKind heap = (mapEdge.useKind() == MapObjectUse) ? JSMapFields : JSSetFields;
1612         read(heap);
1613         def(HeapLocation(MapBucketHeadLoc, heap, mapEdge), LazyNode(node));
1614         return;
1615     }
1616
1617     case GetMapBucketNext: {
1618         AbstractHeapKind heap = (node->bucketOwnerType() == BucketOwnerType::Map) ? JSMapFields : JSSetFields;
1619         read(heap);
1620         Edge& bucketEdge = node->child1();
1621         def(HeapLocation(MapBucketNextLoc, heap, bucketEdge), LazyNode(node));
1622         return;
1623     }
1624
1625     case LoadKeyFromMapBucket: {
1626         AbstractHeapKind heap = (node->bucketOwnerType() == BucketOwnerType::Map) ? JSMapFields : JSSetFields;
1627         read(heap);
1628         Edge& bucketEdge = node->child1();
1629         def(HeapLocation(MapBucketKeyLoc, heap, bucketEdge), LazyNode(node));
1630         return;
1631     }
1632
1633     case LoadValueFromMapBucket: {
1634         AbstractHeapKind heap = (node->bucketOwnerType() == BucketOwnerType::Map) ? JSMapFields : JSSetFields;
1635         read(heap);
1636         Edge& bucketEdge = node->child1();
1637         def(HeapLocation(MapBucketValueLoc, heap, bucketEdge), LazyNode(node));
1638         return;
1639     }
1640
1641     case WeakMapGet: {
1642         Edge& mapEdge = node->child1();
1643         Edge& keyEdge = node->child2();
1644         AbstractHeapKind heap = (mapEdge.useKind() == WeakMapObjectUse) ? JSWeakMapFields : JSWeakSetFields;
1645         read(heap);
1646         def(HeapLocation(WeakMapGetLoc, heap, mapEdge, keyEdge), LazyNode(node));
1647         return;
1648     }
1649
1650     case SetAdd: {
1651         Edge& mapEdge = node->child1();
1652         Edge& keyEdge = node->child2();
1653         write(JSSetFields);
1654         def(HeapLocation(MapBucketLoc, JSSetFields, mapEdge, keyEdge), LazyNode(node));
1655         return;
1656     }
1657
1658     case MapSet: {
1659         Edge& mapEdge = graph.varArgChild(node, 0);
1660         Edge& keyEdge = graph.varArgChild(node, 1);
1661         write(JSMapFields);
1662         def(HeapLocation(MapBucketLoc, JSMapFields, mapEdge, keyEdge), LazyNode(node));
1663         return;
1664     }
1665
1666     case WeakSetAdd: {
1667         Edge& mapEdge = node->child1();
1668         Edge& keyEdge = node->child2();
1669         write(JSWeakSetFields);
1670         def(HeapLocation(WeakMapGetLoc, JSWeakSetFields, mapEdge, keyEdge), LazyNode(keyEdge.node()));
1671         return;
1672     }
1673
1674     case WeakMapSet: {
1675         Edge& mapEdge = graph.varArgChild(node, 0);
1676         Edge& keyEdge = graph.varArgChild(node, 1);
1677         Edge& valueEdge = graph.varArgChild(node, 2);
1678         write(JSWeakMapFields);
1679         def(HeapLocation(WeakMapGetLoc, JSWeakMapFields, mapEdge, keyEdge), LazyNode(valueEdge.node()));
1680         return;
1681     }
1682
1683     case ExtractValueFromWeakMapGet:
1684         def(PureValue(node));
1685         return;
1686
1687     case StringSlice:
1688         def(PureValue(node));
1689         return;
1690
1691     case ToLowerCase:
1692         def(PureValue(node));
1693         return;
1694
1695     case NumberToStringWithValidRadixConstant:
1696         def(PureValue(node, node->validRadixConstant()));
1697         return;
1698         
1699     case LastNodeType:
1700         RELEASE_ASSERT_NOT_REACHED();
1701         return;
1702     }
1703     
1704     DFG_CRASH(graph, node, toCString("Unrecognized node type: ", Graph::opName(node->op())).data());
1705 }
1706
1707 class NoOpClobberize {
1708 public:
1709     NoOpClobberize() { }
1710     template<typename... T>
1711     void operator()(T...) const { }
1712 };
1713
1714 class CheckClobberize {
1715 public:
1716     CheckClobberize()
1717         : m_result(false)
1718     {
1719     }
1720     
1721     template<typename... T>
1722     void operator()(T...) const { m_result = true; }
1723     
1724     bool result() const { return m_result; }
1725     
1726 private:
1727     mutable bool m_result;
1728 };
1729
1730 bool doesWrites(Graph&, Node*);
1731
1732 class AbstractHeapOverlaps {
1733 public:
1734     AbstractHeapOverlaps(AbstractHeap heap)
1735         : m_heap(heap)
1736         , m_result(false)
1737     {
1738     }
1739     
1740     void operator()(AbstractHeap otherHeap) const
1741     {
1742         if (m_result)
1743             return;
1744         m_result = m_heap.overlaps(otherHeap);
1745     }
1746     
1747     bool result() const { return m_result; }
1748
1749 private:
1750     AbstractHeap m_heap;
1751     mutable bool m_result;
1752 };
1753
1754 bool accessesOverlap(Graph&, Node*, AbstractHeap);
1755 bool writesOverlap(Graph&, Node*, AbstractHeap);
1756
1757 bool clobbersHeap(Graph&, Node*);
1758
1759 // We would have used bind() for these, but because of the overlaoding that we are doing,
1760 // it's quite a bit of clearer to just write this out the traditional way.
1761
1762 template<typename T>
1763 class ReadMethodClobberize {
1764 public:
1765     ReadMethodClobberize(T& value)
1766         : m_value(value)
1767     {
1768     }
1769     
1770     void operator()(AbstractHeap heap) const
1771     {
1772         m_value.read(heap);
1773     }
1774 private:
1775     T& m_value;
1776 };
1777
1778 template<typename T>
1779 class WriteMethodClobberize {
1780 public:
1781     WriteMethodClobberize(T& value)
1782         : m_value(value)
1783     {
1784     }
1785     
1786     void operator()(AbstractHeap heap) const
1787     {
1788         m_value.write(heap);
1789     }
1790 private:
1791     T& m_value;
1792 };
1793
1794 template<typename T>
1795 class DefMethodClobberize {
1796 public:
1797     DefMethodClobberize(T& value)
1798         : m_value(value)
1799     {
1800     }
1801     
1802     void operator()(PureValue value) const
1803     {
1804         m_value.def(value);
1805     }
1806     
1807     void operator()(HeapLocation location, LazyNode node) const
1808     {
1809         m_value.def(location, node);
1810     }
1811
1812 private:
1813     T& m_value;
1814 };
1815
1816 template<typename Adaptor>
1817 void clobberize(Graph& graph, Node* node, Adaptor& adaptor)
1818 {
1819     ReadMethodClobberize<Adaptor> read(adaptor);
1820     WriteMethodClobberize<Adaptor> write(adaptor);
1821     DefMethodClobberize<Adaptor> def(adaptor);
1822     clobberize(graph, node, read, write, def);
1823 }
1824
1825 } } // namespace JSC::DFG
1826
1827 #endif // ENABLE(DFG_JIT)