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