[ES6] Handle new_generator_func / new_generator_func_exp in DFG / FTL
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGClobberize.h
1 /*
2  * Copyright (C) 2013-2015 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 #ifndef DFGClobberize_h
27 #define DFGClobberize_h
28
29 #if ENABLE(DFG_JIT)
30
31 #include "DFGAbstractHeap.h"
32 #include "DFGEdgeUsesStructure.h"
33 #include "DFGGraph.h"
34 #include "DFGHeapLocation.h"
35 #include "DFGLazyNode.h"
36 #include "DFGPureValue.h"
37
38 namespace JSC { namespace DFG {
39
40 template<typename ReadFunctor, typename WriteFunctor, typename DefFunctor>
41 void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFunctor& write, const DefFunctor& def)
42 {
43     // Some notes:
44     //
45     // - The canonical way of clobbering the world is to read world and write
46     //   heap. This is because World subsumes Heap and Stack, and Stack can be
47     //   read by anyone but only written to by explicit stack writing operations.
48     //   Of course, claiming to also write World is not wrong; it'll just
49     //   pessimise some important optimizations.
50     //
51     // - We cannot hoist, or sink, anything that has effects. This means that the
52     //   easiest way of indicating that something cannot be hoisted is to claim
53     //   that it side-effects some miscellaneous thing.
54     //
55     // - We cannot hoist forward-exiting nodes without some additional effort. I
56     //   believe that what it comes down to is that forward-exiting generally have
57     //   their NodeExitsForward cleared upon hoist, except for forward-exiting
58     //   nodes that take bogus state as their input. Those are substantially
59     //   harder. We disable it for now. In the future we could enable it by having
60     //   versions of those nodes that backward-exit instead, but I'm not convinced
61     //   of the soundness.
62     //
63     // - Some nodes lie, and claim that they do not read the JSCell_structureID,
64     //   JSCell_typeInfoFlags, etc. These are nodes that use the structure in a way
65     //   that does not depend on things that change under structure transitions.
66     //
67     // - It's implicitly understood that OSR exits read the world. This is why we
68     //   generally don't move or eliminate stores. Every node can exit, so the
69     //   read set does not reflect things that would be read if we exited.
70     //   Instead, the read set reflects what the node will have to read if it
71     //   *doesn't* exit.
72     //
73     // - Broadly, we don't say that we're reading something if that something is
74     //   immutable.
75     //
76     // - We try to make this work even prior to type inference, just so that we
77     //   can use it for IR dumps. No promises on whether the answers are sound
78     //   prior to type inference - though they probably could be if we did some
79     //   small hacking.
80     //
81     // - If you do read(Stack) or read(World), then make sure that readTop() in
82     //   PreciseLocalClobberize is correct.
83     
84     // While read() and write() are fairly self-explanatory - they track what sorts of things the
85     // node may read or write - the def() functor is more tricky. It tells you the heap locations
86     // (not just abstract heaps) that are defined by a node. A heap location comprises an abstract
87     // heap, some nodes, and a LocationKind. Briefly, a location defined by a node is a location
88     // whose value can be deduced from looking at the node itself. The locations returned must obey
89     // the following properties:
90     //
91     // - If someone wants to CSE a load from the heap, then a HeapLocation object should be
92     //   sufficient to find a single matching node.
93     //
94     // - The abstract heap is the only abstract heap that could be clobbered to invalidate any such
95     //   CSE attempt. I.e. if clobberize() reports that on every path between some node and a node
96     //   that defines a HeapLocation that it wanted, there were no writes to any abstract heap that
97     //   overlap the location's heap, then we have a sound match. Effectively, the semantics of
98     //   write() and def() are intertwined such that for them to be sound they must agree on what
99     //   is CSEable.
100     //
101     // read(), write(), and def() for heap locations is enough to do GCSE on effectful things. To
102     // keep things simple, this code will also def() pure things. def() must be overloaded to also
103     // accept PureValue. This way, a client of clobberize() can implement GCSE entirely using the
104     // information that clobberize() passes to write() and def(). Other clients of clobberize() can
105     // just ignore def() by using a NoOpClobberize functor.
106
107     if (edgesUseStructure(graph, node))
108         read(JSCell_structureID);
109     
110     switch (node->op()) {
111     case JSConstant:
112     case DoubleConstant:
113     case Int52Constant:
114         def(PureValue(node, node->constant()));
115         return;
116         
117     case Identity:
118     case Phantom:
119     case Check:
120     case ExtractOSREntryLocal:
121     case CheckStructureImmediate:
122         return;
123         
124     case ArithIMul:
125     case ArithAbs:
126     case ArithClz32:
127     case ArithMin:
128     case ArithMax:
129     case ArithPow:
130     case ArithSqrt:
131     case ArithFRound:
132     case ArithSin:
133     case ArithCos:
134     case ArithLog:
135     case GetScope:
136     case SkipScope:
137     case StringCharCodeAt:
138     case StringFromCharCode:
139     case CompareStrictEq:
140     case IsUndefined:
141     case IsBoolean:
142     case IsNumber:
143     case IsString:
144     case IsObject:
145     case LogicalNot:
146     case CheckInBounds:
147     case DoubleRep:
148     case ValueRep:
149     case Int52Rep:
150     case BooleanToNumber:
151     case FiatInt52:
152     case MakeRope:
153     case StrCat:
154     case ValueToInt32:
155     case GetExecutable:
156     case BottomValue:
157     case TypeOf:
158         def(PureValue(node));
159         return;
160
161     case BitAnd:
162     case BitOr:
163     case BitXor:
164     case BitLShift:
165     case BitRShift:
166     case BitURShift:
167         if (node->child1().useKind() == UntypedUse || node->child2().useKind() == UntypedUse) {
168             read(World);
169             write(Heap);
170             return;
171         }
172         def(PureValue(node));
173         return;
174
175     case ArithRandom:
176         read(MathDotRandomState);
177         write(MathDotRandomState);
178         return;
179         
180     case HasGenericProperty:
181     case HasStructureProperty:
182     case GetEnumerableLength:
183     case GetPropertyEnumerator: {
184         read(Heap);
185         write(SideState);
186         return;
187     }
188
189     case GetDirectPname: {
190         // This reads and writes heap because it can end up calling a generic getByVal 
191         // if the Structure changed, which could in turn end up calling a getter.
192         read(World);
193         write(Heap);
194         return;
195     }
196
197     case ToIndexString:
198     case GetEnumeratorStructurePname:
199     case GetEnumeratorGenericPname: {
200         def(PureValue(node));
201         return;
202     }
203
204     case HasIndexedProperty: {
205         read(JSObject_butterfly);
206         ArrayMode mode = node->arrayMode();
207         switch (mode.type()) {
208         case Array::Int32: {
209             if (mode.isInBounds()) {
210                 read(Butterfly_publicLength);
211                 read(IndexedInt32Properties);
212                 def(HeapLocation(HasIndexedPropertyLoc, IndexedInt32Properties, node->child1(), node->child2()), LazyNode(node));
213                 return;
214             }
215             read(Heap);
216             return;
217         }
218             
219         case Array::Double: {
220             if (mode.isInBounds()) {
221                 read(Butterfly_publicLength);
222                 read(IndexedDoubleProperties);
223                 def(HeapLocation(HasIndexedPropertyLoc, IndexedDoubleProperties, node->child1(), node->child2()), LazyNode(node));
224                 return;
225             }
226             read(Heap);
227             return;
228         }
229             
230         case Array::Contiguous: {
231             if (mode.isInBounds()) {
232                 read(Butterfly_publicLength);
233                 read(IndexedContiguousProperties);
234                 def(HeapLocation(HasIndexedPropertyLoc, IndexedContiguousProperties, node->child1(), node->child2()), LazyNode(node));
235                 return;
236             }
237             read(Heap);
238             return;
239         }
240
241         case Array::ArrayStorage: {
242             if (mode.isInBounds()) {
243                 read(Butterfly_vectorLength);
244                 read(IndexedArrayStorageProperties);
245                 return;
246             }
247             read(Heap);
248             return;
249         }
250
251         default: {
252             read(World);
253             write(Heap);
254             return;
255         }
256         }
257         RELEASE_ASSERT_NOT_REACHED();
258         return;
259     }
260
261     case ArithAdd:
262     case ArithNegate:
263     case ArithMod:
264     case DoubleAsInt32:
265     case UInt32ToNumber:
266         def(PureValue(node, node->arithMode()));
267         return;
268
269     case ArithDiv:
270     case ArithMul:
271     case ArithSub:
272         switch (node->binaryUseKind()) {
273         case Int32Use:
274         case Int52RepUse:
275         case DoubleRepUse:
276             def(PureValue(node, node->arithMode()));
277             return;
278         case UntypedUse:
279             read(World);
280             write(Heap);
281             return;
282         default:
283             DFG_CRASH(graph, node, "Bad use kind");
284         }
285
286     case ArithRound:
287         def(PureValue(node, static_cast<uintptr_t>(node->arithRoundingMode())));
288         return;
289
290     case CheckCell:
291         def(PureValue(CheckCell, AdjacencyList(AdjacencyList::Fixed, node->child1()), node->cellOperand()));
292         return;
293
294     case CheckNotEmpty:
295         def(PureValue(CheckNotEmpty, AdjacencyList(AdjacencyList::Fixed, node->child1())));
296         return;
297
298     case CheckIdent:
299         def(PureValue(CheckIdent, AdjacencyList(AdjacencyList::Fixed, node->child1()), node->uidOperand()));
300         return;
301
302     case ConstantStoragePointer:
303         def(PureValue(node, node->storagePointer()));
304         return;
305          
306     case MovHint:
307     case ZombieHint:
308     case ExitOK:
309     case KillStack:
310     case Upsilon:
311     case Phi:
312     case PhantomLocal:
313     case SetArgument:
314     case Jump:
315     case Branch:
316     case Switch:
317     case Throw:
318     case ForceOSRExit:
319     case CheckBadCell:
320     case Return:
321     case Unreachable:
322     case CheckTierUpInLoop:
323     case CheckTierUpAtReturn:
324     case CheckTierUpAndOSREnter:
325     case CheckTierUpWithNestedTriggerAndOSREnter:
326     case LoopHint:
327     case Breakpoint:
328     case ProfileWillCall:
329     case ProfileDidCall:
330     case ProfileType:
331     case ProfileControlFlow:
332     case StoreBarrier:
333     case PutHint:
334         write(SideState);
335         return;
336         
337     case InvalidationPoint:
338         write(SideState);
339         def(HeapLocation(InvalidationPointLoc, Watchpoint_fire), LazyNode(node));
340         return;
341
342     case Flush:
343         read(AbstractHeap(Stack, node->local()));
344         write(SideState);
345         return;
346
347     case NotifyWrite:
348         write(Watchpoint_fire);
349         write(SideState);
350         return;
351
352     case CreateActivation: {
353         SymbolTable* table = node->castOperand<SymbolTable*>();
354         if (table->singletonScope()->isStillValid())
355             write(Watchpoint_fire);
356         read(HeapObjectCount);
357         write(HeapObjectCount);
358         return;
359     }
360         
361     case CreateDirectArguments:
362     case CreateScopedArguments:
363     case CreateClonedArguments:
364         read(Stack);
365         read(HeapObjectCount);
366         write(HeapObjectCount);
367         return;
368
369     case PhantomDirectArguments:
370     case PhantomClonedArguments:
371         // DFG backend requires that the locals that this reads are flushed. FTL backend can handle those
372         // locals being promoted.
373         if (!isFTL(graph.m_plan.mode))
374             read(Stack);
375         
376         // Even though it's phantom, it still has the property that one can't be replaced with another.
377         read(HeapObjectCount);
378         write(HeapObjectCount);
379         return;
380
381     case ToThis:
382     case CreateThis:
383         read(MiscFields);
384         read(HeapObjectCount);
385         write(HeapObjectCount);
386         return;
387
388     case VarInjectionWatchpoint:
389         read(MiscFields);
390         def(HeapLocation(VarInjectionWatchpointLoc, MiscFields), LazyNode(node));
391         return;
392
393     case IsObjectOrNull:
394         read(MiscFields);
395         def(HeapLocation(IsObjectOrNullLoc, MiscFields, node->child1()), LazyNode(node));
396         return;
397         
398     case IsFunction:
399         read(MiscFields);
400         def(HeapLocation(IsFunctionLoc, MiscFields, node->child1()), LazyNode(node));
401         return;
402         
403     case GetById:
404     case GetByIdFlush:
405     case PutById:
406     case PutByIdFlush:
407     case PutByIdDirect:
408     case PutGetterById:
409     case PutSetterById:
410     case PutGetterSetterById:
411     case PutGetterByVal:
412     case PutSetterByVal:
413     case ArrayPush:
414     case ArrayPop:
415     case Call:
416     case TailCallInlinedCaller:
417     case Construct:
418     case CallVarargs:
419     case CallForwardVarargs:
420     case TailCallVarargsInlinedCaller:
421     case TailCallForwardVarargsInlinedCaller:
422     case ConstructVarargs:
423     case ConstructForwardVarargs:
424     case ToPrimitive:
425     case In:
426     case ValueAdd:
427         read(World);
428         write(Heap);
429         return;
430
431     case TailCall:
432     case TailCallVarargs:
433     case TailCallForwardVarargs:
434         read(World);
435         write(SideState);
436         return;
437         
438     case GetGetter:
439         read(GetterSetter_getter);
440         def(HeapLocation(GetterLoc, GetterSetter_getter, node->child1()), LazyNode(node));
441         return;
442         
443     case GetSetter:
444         read(GetterSetter_setter);
445         def(HeapLocation(SetterLoc, GetterSetter_setter, node->child1()), LazyNode(node));
446         return;
447         
448     case GetCallee:
449         read(AbstractHeap(Stack, JSStack::Callee));
450         def(HeapLocation(StackLoc, AbstractHeap(Stack, JSStack::Callee)), LazyNode(node));
451         return;
452         
453     case GetArgumentCount:
454         read(AbstractHeap(Stack, JSStack::ArgumentCount));
455         def(HeapLocation(StackPayloadLoc, AbstractHeap(Stack, JSStack::ArgumentCount)), LazyNode(node));
456         return;
457
458     case GetRestLength:
459         read(Stack);
460         return;
461         
462     case GetLocal:
463         read(AbstractHeap(Stack, node->local()));
464         def(HeapLocation(StackLoc, AbstractHeap(Stack, node->local())), LazyNode(node));
465         return;
466         
467     case SetLocal:
468         write(AbstractHeap(Stack, node->local()));
469         def(HeapLocation(StackLoc, AbstractHeap(Stack, node->local())), LazyNode(node->child1().node()));
470         return;
471         
472     case GetStack: {
473         AbstractHeap heap(Stack, node->stackAccessData()->local);
474         read(heap);
475         def(HeapLocation(StackLoc, heap), LazyNode(node));
476         return;
477     }
478         
479     case PutStack: {
480         AbstractHeap heap(Stack, node->stackAccessData()->local);
481         write(heap);
482         def(HeapLocation(StackLoc, heap), LazyNode(node->child1().node()));
483         return;
484     }
485         
486     case LoadVarargs: {
487         read(World);
488         write(Heap);
489         LoadVarargsData* data = node->loadVarargsData();
490         write(AbstractHeap(Stack, data->count.offset()));
491         for (unsigned i = data->limit; i--;)
492             write(AbstractHeap(Stack, data->start.offset() + static_cast<int>(i)));
493         return;
494     }
495         
496     case ForwardVarargs: {
497         // We could be way more precise here.
498         read(Stack);
499         
500         LoadVarargsData* data = node->loadVarargsData();
501         write(AbstractHeap(Stack, data->count.offset()));
502         for (unsigned i = data->limit; i--;)
503             write(AbstractHeap(Stack, data->start.offset() + static_cast<int>(i)));
504         return;
505     }
506         
507     case GetLocalUnlinked:
508         read(AbstractHeap(Stack, node->unlinkedLocal()));
509         def(HeapLocation(StackLoc, AbstractHeap(Stack, node->unlinkedLocal())), LazyNode(node));
510         return;
511         
512     case GetByVal: {
513         ArrayMode mode = node->arrayMode();
514         switch (mode.type()) {
515         case Array::SelectUsingPredictions:
516         case Array::Unprofiled:
517         case Array::SelectUsingArguments:
518             // Assume the worst since we don't have profiling yet.
519             read(World);
520             write(Heap);
521             return;
522             
523         case Array::ForceExit:
524             write(SideState);
525             return;
526             
527         case Array::Generic:
528             read(World);
529             write(Heap);
530             return;
531             
532         case Array::String:
533             if (mode.isOutOfBounds()) {
534                 read(World);
535                 write(Heap);
536                 return;
537             }
538             // This appears to read nothing because it's only reading immutable data.
539             def(PureValue(node, mode.asWord()));
540             return;
541             
542         case Array::DirectArguments:
543             read(DirectArgumentsProperties);
544             def(HeapLocation(IndexedPropertyLoc, DirectArgumentsProperties, node->child1(), node->child2()), LazyNode(node));
545             return;
546             
547         case Array::ScopedArguments:
548             read(ScopeProperties);
549             def(HeapLocation(IndexedPropertyLoc, ScopeProperties, node->child1(), node->child2()), LazyNode(node));
550             return;
551             
552         case Array::Int32:
553             if (mode.isInBounds()) {
554                 read(Butterfly_publicLength);
555                 read(IndexedInt32Properties);
556                 def(HeapLocation(IndexedPropertyLoc, IndexedInt32Properties, node->child1(), node->child2()), LazyNode(node));
557                 return;
558             }
559             read(World);
560             write(Heap);
561             return;
562             
563         case Array::Double:
564             if (mode.isInBounds()) {
565                 read(Butterfly_publicLength);
566                 read(IndexedDoubleProperties);
567                 def(HeapLocation(IndexedPropertyLoc, IndexedDoubleProperties, node->child1(), node->child2()), LazyNode(node));
568                 return;
569             }
570             read(World);
571             write(Heap);
572             return;
573             
574         case Array::Contiguous:
575             if (mode.isInBounds()) {
576                 read(Butterfly_publicLength);
577                 read(IndexedContiguousProperties);
578                 def(HeapLocation(IndexedPropertyLoc, IndexedContiguousProperties, node->child1(), node->child2()), LazyNode(node));
579                 return;
580             }
581             read(World);
582             write(Heap);
583             return;
584
585         case Array::Undecided:
586             def(PureValue(node));
587             return;
588             
589         case Array::ArrayStorage:
590         case Array::SlowPutArrayStorage:
591             if (mode.isInBounds()) {
592                 read(Butterfly_vectorLength);
593                 read(IndexedArrayStorageProperties);
594                 return;
595             }
596             read(World);
597             write(Heap);
598             return;
599             
600         case Array::Int8Array:
601         case Array::Int16Array:
602         case Array::Int32Array:
603         case Array::Uint8Array:
604         case Array::Uint8ClampedArray:
605         case Array::Uint16Array:
606         case Array::Uint32Array:
607         case Array::Float32Array:
608         case Array::Float64Array:
609             read(TypedArrayProperties);
610             read(MiscFields);
611             def(HeapLocation(IndexedPropertyLoc, TypedArrayProperties, node->child1(), node->child2()), LazyNode(node));
612             return;
613         // We should not get an AnyTypedArray in a GetByVal as AnyTypedArray is only created from intrinsics, which
614         // are only added from Inline Caching a GetById.
615         case Array::AnyTypedArray:
616             DFG_CRASH(graph, node, "impossible array mode for get");
617             return;
618         }
619         RELEASE_ASSERT_NOT_REACHED();
620         return;
621     }
622         
623     case GetMyArgumentByVal: {
624         read(Stack);
625         // FIXME: It would be trivial to have a def here.
626         // https://bugs.webkit.org/show_bug.cgi?id=143077
627         return;
628     }
629
630     case PutByValDirect:
631     case PutByVal:
632     case PutByValAlias: {
633         ArrayMode mode = node->arrayMode();
634         Node* base = graph.varArgChild(node, 0).node();
635         Node* index = graph.varArgChild(node, 1).node();
636         Node* value = graph.varArgChild(node, 2).node();
637         switch (mode.modeForPut().type()) {
638         case Array::SelectUsingPredictions:
639         case Array::SelectUsingArguments:
640         case Array::Unprofiled:
641         case Array::Undecided:
642             // Assume the worst since we don't have profiling yet.
643             read(World);
644             write(Heap);
645             return;
646             
647         case Array::ForceExit:
648             write(SideState);
649             return;
650             
651         case Array::Generic:
652             read(World);
653             write(Heap);
654             return;
655             
656         case Array::Int32:
657             if (node->arrayMode().isOutOfBounds()) {
658                 read(World);
659                 write(Heap);
660                 return;
661             }
662             read(Butterfly_publicLength);
663             read(Butterfly_vectorLength);
664             read(IndexedInt32Properties);
665             write(IndexedInt32Properties);
666             if (node->arrayMode().mayStoreToHole())
667                 write(Butterfly_publicLength);
668             def(HeapLocation(IndexedPropertyLoc, IndexedInt32Properties, base, index), LazyNode(value));
669             return;
670             
671         case Array::Double:
672             if (node->arrayMode().isOutOfBounds()) {
673                 read(World);
674                 write(Heap);
675                 return;
676             }
677             read(Butterfly_publicLength);
678             read(Butterfly_vectorLength);
679             read(IndexedDoubleProperties);
680             write(IndexedDoubleProperties);
681             if (node->arrayMode().mayStoreToHole())
682                 write(Butterfly_publicLength);
683             def(HeapLocation(IndexedPropertyLoc, IndexedDoubleProperties, base, index), LazyNode(value));
684             return;
685             
686         case Array::Contiguous:
687             if (node->arrayMode().isOutOfBounds()) {
688                 read(World);
689                 write(Heap);
690                 return;
691             }
692             read(Butterfly_publicLength);
693             read(Butterfly_vectorLength);
694             read(IndexedContiguousProperties);
695             write(IndexedContiguousProperties);
696             if (node->arrayMode().mayStoreToHole())
697                 write(Butterfly_publicLength);
698             def(HeapLocation(IndexedPropertyLoc, IndexedContiguousProperties, base, index), LazyNode(value));
699             return;
700             
701         case Array::ArrayStorage:
702         case Array::SlowPutArrayStorage:
703             // Give up on life for now.
704             read(World);
705             write(Heap);
706             return;
707
708         case Array::Int8Array:
709         case Array::Int16Array:
710         case Array::Int32Array:
711         case Array::Uint8Array:
712         case Array::Uint8ClampedArray:
713         case Array::Uint16Array:
714         case Array::Uint32Array:
715         case Array::Float32Array:
716         case Array::Float64Array:
717             read(MiscFields);
718             write(TypedArrayProperties);
719             // FIXME: We can't def() anything here because these operations truncate their inputs.
720             // https://bugs.webkit.org/show_bug.cgi?id=134737
721             return;
722         case Array::AnyTypedArray:
723         case Array::String:
724         case Array::DirectArguments:
725         case Array::ScopedArguments:
726             DFG_CRASH(graph, node, "impossible array mode for put");
727             return;
728         }
729         RELEASE_ASSERT_NOT_REACHED();
730         return;
731     }
732         
733     case CheckStructure:
734         read(JSCell_structureID);
735         return;
736
737     case CheckArray:
738         read(JSCell_indexingType);
739         read(JSCell_typeInfoType);
740         read(JSCell_structureID);
741         return;
742
743     case CheckHasInstance:
744         read(JSCell_typeInfoFlags);
745         def(HeapLocation(CheckHasInstanceLoc, JSCell_typeInfoFlags, node->child1()), LazyNode(node));
746         return;
747
748     case InstanceOf:
749         read(JSCell_structureID);
750         def(HeapLocation(InstanceOfLoc, JSCell_structureID, node->child1(), node->child2()), LazyNode(node));
751         return;
752
753     case PutStructure:
754         write(JSCell_structureID);
755         write(JSCell_typeInfoType);
756         write(JSCell_typeInfoFlags);
757         write(JSCell_indexingType);
758         return;
759         
760     case AllocatePropertyStorage:
761         write(JSObject_butterfly);
762         def(HeapLocation(ButterflyLoc, JSObject_butterfly, node->child1()), LazyNode(node));
763         return;
764         
765     case ReallocatePropertyStorage:
766         read(JSObject_butterfly);
767         write(JSObject_butterfly);
768         def(HeapLocation(ButterflyLoc, JSObject_butterfly, node->child1()), LazyNode(node));
769         return;
770         
771     case GetButterfly:
772         read(JSObject_butterfly);
773         def(HeapLocation(ButterflyLoc, JSObject_butterfly, node->child1()), LazyNode(node));
774         return;
775
776     case GetButterflyReadOnly:
777         // This rule is separate to prevent CSE of GetButterfly with GetButterflyReadOnly. But in reality,
778         // this works because we don't introduce GetButterflyReadOnly until the bitter end of compilation.
779         read(JSObject_butterfly);
780         def(HeapLocation(ButterflyReadOnlyLoc, JSObject_butterfly, node->child1()), LazyNode(node));
781         return;
782         
783     case Arrayify:
784     case ArrayifyToStructure:
785         read(JSCell_structureID);
786         read(JSCell_indexingType);
787         read(JSObject_butterfly);
788         write(JSCell_structureID);
789         write(JSCell_indexingType);
790         write(JSObject_butterfly);
791         write(Watchpoint_fire);
792         return;
793         
794     case GetIndexedPropertyStorage:
795         if (node->arrayMode().type() == Array::String) {
796             def(PureValue(node, node->arrayMode().asWord()));
797             return;
798         }
799         read(MiscFields);
800         def(HeapLocation(IndexedPropertyStorageLoc, MiscFields, node->child1()), LazyNode(node));
801         return;
802         
803     case GetTypedArrayByteOffset:
804         read(MiscFields);
805         def(HeapLocation(TypedArrayByteOffsetLoc, MiscFields, node->child1()), LazyNode(node));
806         return;
807         
808     case GetByOffset:
809     case GetGetterSetterByOffset: {
810         unsigned identifierNumber = node->storageAccessData().identifierNumber;
811         AbstractHeap heap(NamedProperties, identifierNumber);
812         read(heap);
813         def(HeapLocation(NamedPropertyLoc, heap, node->child2()), LazyNode(node));
814         return;
815     }
816         
817     case MultiGetByOffset: {
818         read(JSCell_structureID);
819         read(JSObject_butterfly);
820         AbstractHeap heap(NamedProperties, node->multiGetByOffsetData().identifierNumber);
821         read(heap);
822         def(HeapLocation(NamedPropertyLoc, heap, node->child1()), LazyNode(node));
823         return;
824     }
825         
826     case MultiPutByOffset: {
827         read(JSCell_structureID);
828         read(JSObject_butterfly);
829         AbstractHeap heap(NamedProperties, node->multiPutByOffsetData().identifierNumber);
830         write(heap);
831         if (node->multiPutByOffsetData().writesStructures())
832             write(JSCell_structureID);
833         if (node->multiPutByOffsetData().reallocatesStorage())
834             write(JSObject_butterfly);
835         def(HeapLocation(NamedPropertyLoc, heap, node->child1()), LazyNode(node->child2().node()));
836         return;
837     }
838         
839     case PutByOffset: {
840         unsigned identifierNumber = node->storageAccessData().identifierNumber;
841         AbstractHeap heap(NamedProperties, identifierNumber);
842         write(heap);
843         def(HeapLocation(NamedPropertyLoc, heap, node->child2()), LazyNode(node->child3().node()));
844         return;
845     }
846         
847     case GetArrayLength: {
848         ArrayMode mode = node->arrayMode();
849         switch (mode.type()) {
850         case Array::Int32:
851         case Array::Double:
852         case Array::Contiguous:
853         case Array::ArrayStorage:
854         case Array::SlowPutArrayStorage:
855             read(Butterfly_publicLength);
856             def(HeapLocation(ArrayLengthLoc, Butterfly_publicLength, node->child1()), LazyNode(node));
857             return;
858             
859         case Array::String:
860             def(PureValue(node, mode.asWord()));
861             return;
862
863         case Array::DirectArguments:
864         case Array::ScopedArguments:
865             read(MiscFields);
866             def(HeapLocation(ArrayLengthLoc, MiscFields, node->child1()), LazyNode(node));
867             return;
868
869         default:
870             ASSERT(mode.isSomeTypedArrayView());
871             read(MiscFields);
872             def(HeapLocation(ArrayLengthLoc, MiscFields, node->child1()), LazyNode(node));
873             return;
874         }
875     }
876         
877     case GetClosureVar:
878         read(AbstractHeap(ScopeProperties, node->scopeOffset().offset()));
879         def(HeapLocation(ClosureVariableLoc, AbstractHeap(ScopeProperties, node->scopeOffset().offset()), node->child1()), LazyNode(node));
880         return;
881         
882     case PutClosureVar:
883         write(AbstractHeap(ScopeProperties, node->scopeOffset().offset()));
884         def(HeapLocation(ClosureVariableLoc, AbstractHeap(ScopeProperties, node->scopeOffset().offset()), node->child1()), LazyNode(node->child2().node()));
885         return;
886         
887     case GetFromArguments: {
888         AbstractHeap heap(DirectArgumentsProperties, node->capturedArgumentsOffset().offset());
889         read(heap);
890         def(HeapLocation(DirectArgumentsLoc, heap, node->child1()), LazyNode(node));
891         return;
892     }
893         
894     case PutToArguments: {
895         AbstractHeap heap(DirectArgumentsProperties, node->capturedArgumentsOffset().offset());
896         write(heap);
897         def(HeapLocation(DirectArgumentsLoc, heap, node->child1()), LazyNode(node->child2().node()));
898         return;
899     }
900         
901     case GetGlobalVar:
902     case GetGlobalLexicalVariable:
903         read(AbstractHeap(Absolute, node->variablePointer()));
904         def(HeapLocation(GlobalVariableLoc, AbstractHeap(Absolute, node->variablePointer())), LazyNode(node));
905         return;
906         
907     case PutGlobalVariable:
908         write(AbstractHeap(Absolute, node->variablePointer()));
909         def(HeapLocation(GlobalVariableLoc, AbstractHeap(Absolute, node->variablePointer())), LazyNode(node->child2().node()));
910         return;
911
912     case NewArrayWithSize:
913     case NewTypedArray:
914         read(HeapObjectCount);
915         write(HeapObjectCount);
916         return;
917
918     case NewArray: {
919         read(HeapObjectCount);
920         write(HeapObjectCount);
921
922         unsigned numElements = node->numChildren();
923
924         def(HeapLocation(ArrayLengthLoc, Butterfly_publicLength, node),
925             LazyNode(graph.freeze(jsNumber(numElements))));
926
927         if (!numElements)
928             return;
929
930         AbstractHeap heap;
931         switch (node->indexingType()) {
932         case ALL_DOUBLE_INDEXING_TYPES:
933             heap = IndexedDoubleProperties;
934             break;
935
936         case ALL_INT32_INDEXING_TYPES:
937             heap = IndexedInt32Properties;
938             break;
939
940         case ALL_CONTIGUOUS_INDEXING_TYPES:
941             heap = IndexedContiguousProperties;
942             break;
943
944         default:
945             return;
946         }
947
948         if (numElements < graph.m_uint32ValuesInUse.size()) {
949             for (unsigned operandIdx = 0; operandIdx < numElements; ++operandIdx) {
950                 Edge use = graph.m_varArgChildren[node->firstChild() + operandIdx];
951                 def(HeapLocation(IndexedPropertyLoc, heap, node, LazyNode(graph.freeze(jsNumber(operandIdx)))),
952                     LazyNode(use.node()));
953             }
954         } else {
955             for (uint32_t operandIdx : graph.m_uint32ValuesInUse) {
956                 if (operandIdx >= numElements)
957                     continue;
958                 Edge use = graph.m_varArgChildren[node->firstChild() + operandIdx];
959                 // operandIdx comes from graph.m_uint32ValuesInUse and thus is guaranteed to be already frozen
960                 def(HeapLocation(IndexedPropertyLoc, heap, node, LazyNode(graph.freeze(jsNumber(operandIdx)))),
961                     LazyNode(use.node()));
962             }
963         }
964         return;
965     }
966
967     case NewArrayBuffer: {
968         read(HeapObjectCount);
969         write(HeapObjectCount);
970
971         unsigned numElements = node->numConstants();
972         def(HeapLocation(ArrayLengthLoc, Butterfly_publicLength, node),
973             LazyNode(graph.freeze(jsNumber(numElements))));
974
975         AbstractHeap heap;
976         NodeType op = JSConstant;
977         switch (node->indexingType()) {
978         case ALL_DOUBLE_INDEXING_TYPES:
979             heap = IndexedDoubleProperties;
980             op = DoubleConstant;
981             break;
982
983         case ALL_INT32_INDEXING_TYPES:
984             heap = IndexedInt32Properties;
985             break;
986
987         case ALL_CONTIGUOUS_INDEXING_TYPES:
988             heap = IndexedContiguousProperties;
989             break;
990
991         default:
992             return;
993         }
994
995         JSValue* data = graph.m_codeBlock->constantBuffer(node->startConstant());
996         if (numElements < graph.m_uint32ValuesInUse.size()) {
997             for (unsigned index = 0; index < numElements; ++index) {
998                 def(HeapLocation(IndexedPropertyLoc, heap, node, LazyNode(graph.freeze(jsNumber(index)))),
999                     LazyNode(graph.freeze(data[index]), op));
1000             }
1001         } else {
1002             Vector<uint32_t> possibleIndices;
1003             for (uint32_t index : graph.m_uint32ValuesInUse) {
1004                 if (index >= numElements)
1005                     continue;
1006                 possibleIndices.append(index);
1007             }
1008             for (uint32_t index : possibleIndices) {
1009                 def(HeapLocation(IndexedPropertyLoc, heap, node, LazyNode(graph.freeze(jsNumber(index)))),
1010                     LazyNode(graph.freeze(data[index]), op));
1011             }
1012         }
1013         return;
1014     }
1015
1016     case CopyRest: {
1017         read(Stack);
1018         write(Heap);
1019         return;
1020     }
1021
1022     case NewObject:
1023     case NewRegexp:
1024     case NewStringObject:
1025     case PhantomNewObject:
1026     case MaterializeNewObject:
1027     case PhantomNewFunction:
1028     case PhantomCreateActivation:
1029     case MaterializeCreateActivation:
1030         read(HeapObjectCount);
1031         write(HeapObjectCount);
1032         return;
1033     
1034     case NewArrowFunction:
1035     case NewFunction:
1036     case NewGeneratorFunction:
1037         if (node->castOperand<FunctionExecutable*>()->singletonFunction()->isStillValid())
1038             write(Watchpoint_fire);
1039         read(HeapObjectCount);
1040         write(HeapObjectCount);
1041         return;
1042
1043     case RegExpExec:
1044     case RegExpTest:
1045         read(RegExpState);
1046         write(RegExpState);
1047         return;
1048
1049     case StringCharAt:
1050         if (node->arrayMode().isOutOfBounds()) {
1051             read(World);
1052             write(Heap);
1053             return;
1054         }
1055         def(PureValue(node));
1056         return;
1057         
1058     case CompareEq:
1059     case CompareLess:
1060     case CompareLessEq:
1061     case CompareGreater:
1062     case CompareGreaterEq:
1063         if (!node->isBinaryUseKind(UntypedUse)) {
1064             def(PureValue(node));
1065             return;
1066         }
1067         read(World);
1068         write(Heap);
1069         return;
1070         
1071     case ToString:
1072     case CallStringConstructor:
1073         switch (node->child1().useKind()) {
1074         case StringObjectUse:
1075         case StringOrStringObjectUse:
1076             // These don't def a pure value, unfortunately. I'll avoid load-eliminating these for
1077             // now.
1078             return;
1079             
1080         case CellUse:
1081         case UntypedUse:
1082             read(World);
1083             write(Heap);
1084             return;
1085             
1086         default:
1087             RELEASE_ASSERT_NOT_REACHED();
1088             return;
1089         }
1090         
1091     case ThrowReferenceError:
1092         write(SideState);
1093         return;
1094         
1095     case CountExecution:
1096     case CheckWatchdogTimer:
1097         read(InternalState);
1098         write(InternalState);
1099         return;
1100         
1101     case LastNodeType:
1102         RELEASE_ASSERT_NOT_REACHED();
1103         return;
1104     }
1105     
1106     DFG_CRASH(graph, node, toCString("Unrecognized node type: ", Graph::opName(node->op())).data());
1107 }
1108
1109 class NoOpClobberize {
1110 public:
1111     NoOpClobberize() { }
1112     template<typename... T>
1113     void operator()(T...) const { }
1114 };
1115
1116 class CheckClobberize {
1117 public:
1118     CheckClobberize()
1119         : m_result(false)
1120     {
1121     }
1122     
1123     template<typename... T>
1124     void operator()(T...) const { m_result = true; }
1125     
1126     bool result() const { return m_result; }
1127     
1128 private:
1129     mutable bool m_result;
1130 };
1131
1132 bool doesWrites(Graph&, Node*);
1133
1134 class AbstractHeapOverlaps {
1135 public:
1136     AbstractHeapOverlaps(AbstractHeap heap)
1137         : m_heap(heap)
1138         , m_result(false)
1139     {
1140     }
1141     
1142     void operator()(AbstractHeap otherHeap) const
1143     {
1144         if (m_result)
1145             return;
1146         m_result = m_heap.overlaps(otherHeap);
1147     }
1148     
1149     bool result() const { return m_result; }
1150
1151 private:
1152     AbstractHeap m_heap;
1153     mutable bool m_result;
1154 };
1155
1156 bool accessesOverlap(Graph&, Node*, AbstractHeap);
1157 bool writesOverlap(Graph&, Node*, AbstractHeap);
1158
1159 bool clobbersHeap(Graph&, Node*);
1160
1161 // We would have used bind() for these, but because of the overlaoding that we are doing,
1162 // it's quite a bit of clearer to just write this out the traditional way.
1163
1164 template<typename T>
1165 class ReadMethodClobberize {
1166 public:
1167     ReadMethodClobberize(T& value)
1168         : m_value(value)
1169     {
1170     }
1171     
1172     void operator()(AbstractHeap heap) const
1173     {
1174         m_value.read(heap);
1175     }
1176 private:
1177     T& m_value;
1178 };
1179
1180 template<typename T>
1181 class WriteMethodClobberize {
1182 public:
1183     WriteMethodClobberize(T& value)
1184         : m_value(value)
1185     {
1186     }
1187     
1188     void operator()(AbstractHeap heap) const
1189     {
1190         m_value.write(heap);
1191     }
1192 private:
1193     T& m_value;
1194 };
1195
1196 template<typename T>
1197 class DefMethodClobberize {
1198 public:
1199     DefMethodClobberize(T& value)
1200         : m_value(value)
1201     {
1202     }
1203     
1204     void operator()(PureValue value) const
1205     {
1206         m_value.def(value);
1207     }
1208     
1209     void operator()(HeapLocation location, LazyNode node) const
1210     {
1211         m_value.def(location, node);
1212     }
1213
1214 private:
1215     T& m_value;
1216 };
1217
1218 template<typename Adaptor>
1219 void clobberize(Graph& graph, Node* node, Adaptor& adaptor)
1220 {
1221     ReadMethodClobberize<Adaptor> read(adaptor);
1222     WriteMethodClobberize<Adaptor> write(adaptor);
1223     DefMethodClobberize<Adaptor> def(adaptor);
1224     clobberize(graph, node, read, write, def);
1225 }
1226
1227 } } // namespace JSC::DFG
1228
1229 #endif // ENABLE(DFG_JIT)
1230
1231 #endif // DFGClobberize_h
1232