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