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