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