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