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