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