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