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