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