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