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