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