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