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