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