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