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