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