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