DFG should only have two mechanisms for describing effectfulness of nodes; previously...
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGClobberize.h
1 /*
2  * Copyright (C) 2013-2015 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 "DFGPureValue.h"
36
37 namespace JSC { namespace DFG {
38
39 template<typename ReadFunctor, typename WriteFunctor, typename DefFunctor>
40 void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFunctor& write, const DefFunctor& def)
41 {
42     // Some notes:
43     //
44     // - We cannot hoist, or sink, anything that has effects. This means that the
45     //   easiest way of indicating that something cannot be hoisted is to claim
46     //   that it side-effects some miscellaneous thing.
47     //
48     // - We cannot hoist forward-exiting nodes without some additional effort. I
49     //   believe that what it comes down to is that forward-exiting generally have
50     //   their NodeExitsForward cleared upon hoist, except for forward-exiting
51     //   nodes that take bogus state as their input. Those are substantially
52     //   harder. We disable it for now. In the future we could enable it by having
53     //   versions of those nodes that backward-exit instead, but I'm not convinced
54     //   of the soundness.
55     //
56     // - Some nodes lie, and claim that they do not read the JSCell_structureID, JSCell_typeInfoFlags, etc.
57     //   These are nodes that use the structure in a way that does not depend on
58     //   things that change under structure transitions.
59     //
60     // - It's implicitly understood that OSR exits read the world. This is why we
61     //   generally don't move or eliminate stores. Every node can exit, so the
62     //   read set does not reflect things that would be read if we exited.
63     //   Instead, the read set reflects what the node will have to read if it
64     //   *doesn't* exit.
65     //
66     // - Broadly, we don't say that we're reading something if that something is
67     //   immutable.
68     //
69     // - We try to make this work even prior to type inference, just so that we
70     //   can use it for IR dumps. No promises on whether the answers are sound
71     //   prior to type inference - though they probably could be if we did some
72     //   small hacking.
73     
74     // While read() and write() are fairly self-explanatory - they track what sorts of things the
75     // node may read or write - the def() functor is more tricky. It tells you the heap locations
76     // (not just abstract heaps) that are defined by a node. A heap location comprises an abstract
77     // heap, some nodes, and a LocationKind. Briefly, a location defined by a node is a location
78     // whose value can be deduced from looking at the node itself. The locations returned must obey
79     // the following properties:
80     //
81     // - If someone wants to CSE a load from the heap, then a HeapLocation object should be
82     //   sufficient to find a single matching node.
83     //
84     // - The abstract heap is the only abstract heap that could be clobbered to invalidate any such
85     //   CSE attempt. I.e. if clobberize() reports that on every path between some node and a node
86     //   that defines a HeapLocation that it wanted, there were no writes to any abstract heap that
87     //   overlap the location's heap, then we have a sound match. Effectively, the semantics of
88     //   write() and def() are intertwined such that for them to be sound they must agree on what
89     //   is CSEable.
90     //
91     // read(), write(), and def() for heap locations is enough to do GCSE on effectful things. To
92     // keep things simple, this code will also def() pure things. def() must be overloaded to also
93     // accept PureValue. This way, a client of clobberize() can implement GCSE entirely using the
94     // information that clobberize() passes to write() and def(). Other clients of clobberize() can
95     // just ignore def() by using a NoOpClobberize functor.
96
97     if (edgesUseStructure(graph, node))
98         read(JSCell_structureID);
99     
100     switch (node->op()) {
101     case JSConstant:
102     case DoubleConstant:
103     case Int52Constant:
104         def(PureValue(node, node->constant()));
105         return;
106         
107     case Identity:
108     case Phantom:
109     case HardPhantom:
110     case Check:
111     case ExtractOSREntryLocal:
112     case CheckStructureImmediate:
113         return;
114         
115     case BitAnd:
116     case BitOr:
117     case BitXor:
118     case BitLShift:
119     case BitRShift:
120     case BitURShift:
121     case ArithIMul:
122     case ArithAbs:
123     case ArithMin:
124     case ArithMax:
125     case ArithSqrt:
126     case ArithFRound:
127     case ArithSin:
128     case ArithCos:
129     case GetScope:
130     case SkipScope:
131     case StringCharCodeAt:
132     case StringFromCharCode:
133     case CompareEqConstant:
134     case CompareStrictEq:
135     case IsUndefined:
136     case IsBoolean:
137     case IsNumber:
138     case IsString:
139     case LogicalNot:
140     case CheckInBounds:
141     case DoubleRep:
142     case ValueRep:
143     case Int52Rep:
144     case BooleanToNumber:
145     case FiatInt52:
146     case MakeRope:
147     case ValueToInt32:
148     case GetExecutable:
149     case BottomValue:
150         def(PureValue(node));
151         return;
152         
153     case HasGenericProperty:
154     case HasStructureProperty:
155     case GetEnumerableLength:
156     case GetStructurePropertyEnumerator:
157     case GetGenericPropertyEnumerator: {
158         read(World);
159         write(SideState);
160         return;
161     }
162
163     case GetDirectPname: {
164         // This reads and writes world because it can end up calling a generic getByVal 
165         // if the Structure changed, which could in turn end up calling a getter.
166         read(World);
167         write(World);
168         return;
169     }
170
171     case ToIndexString:
172     case GetEnumeratorPname: {
173         def(PureValue(node));
174         return;
175     }
176
177     case HasIndexedProperty: {
178         read(JSObject_butterfly);
179         ArrayMode mode = node->arrayMode();
180         switch (mode.type()) {
181         case Array::Int32: {
182             if (mode.isInBounds()) {
183                 read(Butterfly_publicLength);
184                 read(IndexedInt32Properties);
185                 def(HeapLocation(HasIndexedPropertyLoc, IndexedInt32Properties, node->child1(), node->child2()), node);
186                 return;
187             }
188             read(World);
189             return;
190         }
191             
192         case Array::Double: {
193             if (mode.isInBounds()) {
194                 read(Butterfly_publicLength);
195                 read(IndexedDoubleProperties);
196                 def(HeapLocation(HasIndexedPropertyLoc, IndexedDoubleProperties, node->child1(), node->child2()), node);
197                 return;
198             }
199             read(World);
200             return;
201         }
202             
203         case Array::Contiguous: {
204             if (mode.isInBounds()) {
205                 read(Butterfly_publicLength);
206                 read(IndexedContiguousProperties);
207                 def(HeapLocation(HasIndexedPropertyLoc, IndexedContiguousProperties, node->child1(), node->child2()), node);
208                 return;
209             }
210             read(World);
211             return;
212         }
213
214         case Array::ArrayStorage: {
215             if (mode.isInBounds()) {
216                 read(Butterfly_vectorLength);
217                 read(IndexedArrayStorageProperties);
218                 return;
219             }
220             read(World);
221             return;
222         }
223
224         default: {
225             read(World);
226             write(World);
227             return;
228         }
229         }
230         RELEASE_ASSERT_NOT_REACHED();
231         return;
232     }
233
234     case ArithAdd:
235     case ArithSub:
236     case ArithNegate:
237     case ArithMul:
238     case ArithDiv:
239     case ArithMod:
240     case DoubleAsInt32:
241     case UInt32ToNumber:
242         def(PureValue(node, node->arithMode()));
243         return;
244         
245     case CheckCell:
246         def(PureValue(CheckCell, AdjacencyList(AdjacencyList::Fixed, node->child1()), node->cellOperand()));
247         return;
248         
249     case ConstantStoragePointer:
250         def(PureValue(node, node->storagePointer()));
251         return;
252          
253     case MovHint:
254     case ZombieHint:
255     case KillLocal:
256     case Upsilon:
257     case Phi:
258     case PhantomLocal:
259     case SetArgument:
260     case PhantomArguments:
261     case Jump:
262     case Branch:
263     case Switch:
264     case Throw:
265     case ForceOSRExit:
266     case CheckBadCell:
267     case Return:
268     case Unreachable:
269     case CheckTierUpInLoop:
270     case CheckTierUpAtReturn:
271     case CheckTierUpAndOSREnter:
272     case LoopHint:
273     case Breakpoint:
274     case ProfileWillCall:
275     case ProfileDidCall:
276     case ProfileType:
277     case ProfileControlFlow:
278     case StoreBarrier:
279     case StoreBarrierWithNullCheck:
280     case PutByOffsetHint:
281     case PutStructureHint:
282         write(SideState);
283         return;
284         
285     case InvalidationPoint:
286         write(SideState);
287         def(HeapLocation(InvalidationPointLoc, Watchpoint_fire), node);
288         return;
289
290     case Flush:
291         read(AbstractHeap(Variables, node->local()));
292         write(SideState);
293         return;
294
295     case VariableWatchpoint:
296     case TypedArrayWatchpoint:
297         read(Watchpoint_fire);
298         write(SideState);
299         return;
300         
301     case NotifyWrite:
302         write(Watchpoint_fire);
303         write(SideState);
304         return;
305
306     case CreateActivation:
307         read(HeapObjectCount);
308         write(HeapObjectCount);
309         write(SideState);
310         write(Watchpoint_fire);
311         return;
312         
313     case CreateArguments:
314         read(Variables);
315         read(HeapObjectCount);
316         write(HeapObjectCount);
317         write(SideState);
318         write(Watchpoint_fire);
319         return;
320
321     case FunctionReentryWatchpoint:
322         read(Watchpoint_fire);
323         return;
324
325     case ToThis:
326     case CreateThis:
327         read(MiscFields);
328         read(HeapObjectCount);
329         write(HeapObjectCount);
330         return;
331
332     case VarInjectionWatchpoint:
333         read(MiscFields);
334         def(HeapLocation(VarInjectionWatchpointLoc, MiscFields), node);
335         return;
336
337     case AllocationProfileWatchpoint:
338         read(MiscFields);
339         def(HeapLocation(AllocationProfileWatchpointLoc, MiscFields), node);
340         return;
341         
342     case IsObject:
343         read(MiscFields);
344         def(HeapLocation(IsObjectLoc, MiscFields, node->child1()), node);
345         return;
346         
347     case IsFunction:
348         read(MiscFields);
349         def(HeapLocation(IsFunctionLoc, MiscFields, node->child1()), node);
350         return;
351         
352     case TypeOf:
353         read(MiscFields);
354         def(HeapLocation(TypeOfLoc, MiscFields, node->child1()), node);
355         return;
356
357     case GetById:
358     case GetByIdFlush:
359     case PutById:
360     case PutByIdFlush:
361     case PutByIdDirect:
362     case ArrayPush:
363     case ArrayPop:
364     case Call:
365     case Construct:
366     case NativeCall:
367     case NativeConstruct:
368     case ToPrimitive:
369     case In:
370     case GetMyArgumentsLengthSafe:
371     case GetMyArgumentByValSafe:
372     case ValueAdd:
373         read(World);
374         write(World);
375         return;
376         
377     case GetGetter:
378         read(GetterSetter_getter);
379         def(HeapLocation(GetterLoc, GetterSetter_getter, node->child1()), node);
380         return;
381         
382     case GetSetter:
383         read(GetterSetter_setter);
384         def(HeapLocation(SetterLoc, GetterSetter_setter, node->child1()), node);
385         return;
386         
387     case GetCallee:
388         read(AbstractHeap(Variables, JSStack::Callee));
389         def(HeapLocation(VariableLoc, AbstractHeap(Variables, JSStack::Callee)), node);
390         return;
391         
392     case GetLocal:
393     case GetArgument:
394         read(AbstractHeap(Variables, node->local()));
395         def(HeapLocation(VariableLoc, AbstractHeap(Variables, node->local())), node);
396         return;
397         
398     case SetLocal:
399     case PutLocal:
400         write(AbstractHeap(Variables, node->local()));
401         def(HeapLocation(VariableLoc, AbstractHeap(Variables, node->local())), node->child1().node());
402         return;
403         
404     case GetLocalUnlinked:
405         read(AbstractHeap(Variables, node->unlinkedLocal()));
406         def(HeapLocation(VariableLoc, AbstractHeap(Variables, node->unlinkedLocal())), node);
407         return;
408         
409     case GetByVal: {
410         ArrayMode mode = node->arrayMode();
411         switch (mode.type()) {
412         case Array::SelectUsingPredictions:
413         case Array::Unprofiled:
414         case Array::Undecided:
415             // Assume the worst since we don't have profiling yet.
416             read(World);
417             write(World);
418             return;
419             
420         case Array::ForceExit:
421             write(SideState);
422             return;
423             
424         case Array::Generic:
425             read(World);
426             write(World);
427             return;
428             
429         case Array::String:
430             if (mode.isOutOfBounds()) {
431                 read(World);
432                 write(World);
433                 return;
434             }
435             // This appears to read nothing because it's only reading immutable data.
436             def(PureValue(node, mode.asWord()));
437             return;
438             
439         case Array::Arguments:
440             read(Arguments_registers);
441             read(Variables);
442             def(HeapLocation(IndexedPropertyLoc, Variables, node->child1(), node->child2()), node);
443             return;
444             
445         case Array::Int32:
446             if (mode.isInBounds()) {
447                 read(Butterfly_publicLength);
448                 read(IndexedInt32Properties);
449                 def(HeapLocation(IndexedPropertyLoc, IndexedInt32Properties, node->child1(), node->child2()), node);
450                 return;
451             }
452             read(World);
453             write(World);
454             return;
455             
456         case Array::Double:
457             if (mode.isInBounds()) {
458                 read(Butterfly_publicLength);
459                 read(IndexedDoubleProperties);
460                 def(HeapLocation(IndexedPropertyLoc, IndexedDoubleProperties, node->child1(), node->child2()), node);
461                 return;
462             }
463             read(World);
464             write(World);
465             return;
466             
467         case Array::Contiguous:
468             if (mode.isInBounds()) {
469                 read(Butterfly_publicLength);
470                 read(IndexedContiguousProperties);
471                 def(HeapLocation(IndexedPropertyLoc, IndexedContiguousProperties, node->child1(), node->child2()), node);
472                 return;
473             }
474             read(World);
475             write(World);
476             return;
477             
478         case Array::ArrayStorage:
479         case Array::SlowPutArrayStorage:
480             if (mode.isInBounds()) {
481                 read(Butterfly_vectorLength);
482                 read(IndexedArrayStorageProperties);
483                 return;
484             }
485             read(World);
486             write(World);
487             return;
488             
489         case Array::Int8Array:
490         case Array::Int16Array:
491         case Array::Int32Array:
492         case Array::Uint8Array:
493         case Array::Uint8ClampedArray:
494         case Array::Uint16Array:
495         case Array::Uint32Array:
496         case Array::Float32Array:
497         case Array::Float64Array:
498             read(TypedArrayProperties);
499             read(MiscFields);
500             def(HeapLocation(IndexedPropertyLoc, TypedArrayProperties, node->child1(), node->child2()), node);
501             return;
502         }
503         RELEASE_ASSERT_NOT_REACHED();
504         return;
505     }
506
507     case PutByValDirect:
508     case PutByVal:
509     case PutByValAlias: {
510         ArrayMode mode = node->arrayMode();
511         Node* base = graph.varArgChild(node, 0).node();
512         Node* index = graph.varArgChild(node, 1).node();
513         Node* value = graph.varArgChild(node, 2).node();
514         switch (mode.modeForPut().type()) {
515         case Array::SelectUsingPredictions:
516         case Array::Unprofiled:
517         case Array::Undecided:
518         case Array::String:
519             // Assume the worst since we don't have profiling yet.
520             read(World);
521             write(World);
522             return;
523             
524         case Array::ForceExit:
525             write(SideState);
526             return;
527             
528         case Array::Generic:
529             read(World);
530             write(World);
531             return;
532             
533         case Array::Arguments:
534             read(Arguments_registers);
535             read(MiscFields);
536             write(Variables);
537             def(HeapLocation(IndexedPropertyLoc, Variables, base, index), value);
538             return;
539             
540         case Array::Int32:
541             if (node->arrayMode().isOutOfBounds()) {
542                 read(World);
543                 write(World);
544                 return;
545             }
546             read(Butterfly_publicLength);
547             read(Butterfly_vectorLength);
548             read(IndexedInt32Properties);
549             write(IndexedInt32Properties);
550             if (node->arrayMode().mayStoreToHole())
551                 write(Butterfly_publicLength);
552             def(HeapLocation(IndexedPropertyLoc, IndexedInt32Properties, base, index), value);
553             return;
554             
555         case Array::Double:
556             if (node->arrayMode().isOutOfBounds()) {
557                 read(World);
558                 write(World);
559                 return;
560             }
561             read(Butterfly_publicLength);
562             read(Butterfly_vectorLength);
563             read(IndexedDoubleProperties);
564             write(IndexedDoubleProperties);
565             if (node->arrayMode().mayStoreToHole())
566                 write(Butterfly_publicLength);
567             def(HeapLocation(IndexedPropertyLoc, IndexedDoubleProperties, base, index), value);
568             return;
569             
570         case Array::Contiguous:
571             if (node->arrayMode().isOutOfBounds()) {
572                 read(World);
573                 write(World);
574                 return;
575             }
576             read(Butterfly_publicLength);
577             read(Butterfly_vectorLength);
578             read(IndexedContiguousProperties);
579             write(IndexedContiguousProperties);
580             if (node->arrayMode().mayStoreToHole())
581                 write(Butterfly_publicLength);
582             def(HeapLocation(IndexedPropertyLoc, IndexedContiguousProperties, base, index), value);
583             return;
584             
585         case Array::ArrayStorage:
586         case Array::SlowPutArrayStorage:
587             // Give up on life for now.
588             read(World);
589             write(World);
590             return;
591
592         case Array::Int8Array:
593         case Array::Int16Array:
594         case Array::Int32Array:
595         case Array::Uint8Array:
596         case Array::Uint8ClampedArray:
597         case Array::Uint16Array:
598         case Array::Uint32Array:
599         case Array::Float32Array:
600         case Array::Float64Array:
601             read(MiscFields);
602             write(TypedArrayProperties);
603             // FIXME: We can't def() anything here because these operations truncate their inputs.
604             // https://bugs.webkit.org/show_bug.cgi?id=134737
605             return;
606         }
607         RELEASE_ASSERT_NOT_REACHED();
608         return;
609     }
610         
611     case CheckStructure:
612         read(JSCell_structureID);
613         return;
614
615     case CheckArray:
616         read(JSCell_indexingType);
617         read(JSCell_typeInfoType);
618         read(JSCell_structureID);
619         return;
620
621     case CheckHasInstance:
622         read(JSCell_typeInfoFlags);
623         def(HeapLocation(CheckHasInstanceLoc, JSCell_typeInfoFlags, node->child1()), node);
624         return;
625
626     case InstanceOf:
627         read(JSCell_structureID);
628         def(HeapLocation(InstanceOfLoc, JSCell_structureID, node->child1(), node->child2()), node);
629         return;
630
631     case PutStructure:
632         write(JSCell_structureID);
633         write(JSCell_typeInfoType);
634         write(JSCell_typeInfoFlags);
635         write(JSCell_indexingType);
636         return;
637         
638     case AllocatePropertyStorage:
639         write(JSObject_butterfly);
640         def(HeapLocation(ButterflyLoc, JSObject_butterfly, node->child1()), node);
641         return;
642         
643     case ReallocatePropertyStorage:
644         read(JSObject_butterfly);
645         write(JSObject_butterfly);
646         def(HeapLocation(ButterflyLoc, JSObject_butterfly, node->child1()), node);
647         return;
648         
649     case GetButterfly:
650         read(JSObject_butterfly);
651         def(HeapLocation(ButterflyLoc, JSObject_butterfly, node->child1()), node);
652         return;
653         
654     case Arrayify:
655     case ArrayifyToStructure:
656         read(JSCell_structureID);
657         read(JSCell_indexingType);
658         read(JSObject_butterfly);
659         write(JSCell_structureID);
660         write(JSCell_indexingType);
661         write(JSObject_butterfly);
662         write(Watchpoint_fire);
663         return;
664         
665     case GetIndexedPropertyStorage:
666         if (node->arrayMode().type() == Array::String) {
667             def(PureValue(node, node->arrayMode().asWord()));
668             return;
669         }
670         read(MiscFields);
671         def(HeapLocation(IndexedPropertyStorageLoc, MiscFields, node->child1()), node);
672         return;
673         
674     case GetTypedArrayByteOffset:
675         read(MiscFields);
676         def(HeapLocation(TypedArrayByteOffsetLoc, MiscFields, node->child1()), node);
677         return;
678         
679     case GetByOffset:
680     case GetGetterSetterByOffset: {
681         unsigned identifierNumber = node->storageAccessData().identifierNumber;
682         AbstractHeap heap(NamedProperties, identifierNumber);
683         read(heap);
684         def(HeapLocation(NamedPropertyLoc, heap, node->child2()), node);
685         return;
686     }
687         
688     case MultiGetByOffset: {
689         read(JSCell_structureID);
690         read(JSObject_butterfly);
691         AbstractHeap heap(NamedProperties, node->multiGetByOffsetData().identifierNumber);
692         read(heap);
693         def(HeapLocation(NamedPropertyLoc, heap, node->child1()), node);
694         return;
695     }
696         
697     case MultiPutByOffset: {
698         read(JSCell_structureID);
699         read(JSObject_butterfly);
700         AbstractHeap heap(NamedProperties, node->multiPutByOffsetData().identifierNumber);
701         write(heap);
702         if (node->multiPutByOffsetData().writesStructures())
703             write(JSCell_structureID);
704         if (node->multiPutByOffsetData().reallocatesStorage())
705             write(JSObject_butterfly);
706         def(HeapLocation(NamedPropertyLoc, heap, node->child1()), node->child2().node());
707         return;
708     }
709         
710     case PutByOffset: {
711         unsigned identifierNumber = node->storageAccessData().identifierNumber;
712         AbstractHeap heap(NamedProperties, identifierNumber);
713         write(heap);
714         def(HeapLocation(NamedPropertyLoc, heap, node->child2()), node->child3().node());
715         return;
716     }
717         
718     case GetArrayLength: {
719         ArrayMode mode = node->arrayMode();
720         switch (mode.type()) {
721         case Array::Int32:
722         case Array::Double:
723         case Array::Contiguous:
724         case Array::ArrayStorage:
725         case Array::SlowPutArrayStorage:
726             read(Butterfly_publicLength);
727             def(HeapLocation(ArrayLengthLoc, Butterfly_publicLength, node->child1()), node);
728             return;
729             
730         case Array::String:
731             def(PureValue(node, mode.asWord()));
732             return;
733             
734         case Array::Arguments:
735             read(MiscFields);
736             def(HeapLocation(ArrayLengthLoc, MiscFields, node->child1()), node);
737             return;
738             
739         default:
740             ASSERT(mode.typedArrayType() != NotTypedArray);
741             read(MiscFields);
742             def(HeapLocation(ArrayLengthLoc, MiscFields, node->child1()), node);
743             return;
744         }
745     }
746         
747     case GetClosureRegisters:
748         read(JSEnvironmentRecord_registers);
749         def(HeapLocation(ClosureRegistersLoc, JSEnvironmentRecord_registers, node->child1()), node);
750         return;
751
752     case GetClosureVar:
753         read(AbstractHeap(Variables, node->varNumber()));
754         def(HeapLocation(ClosureVariableLoc, AbstractHeap(Variables, node->varNumber()), node->child1()), node);
755         return;
756         
757     case PutClosureVar:
758         write(AbstractHeap(Variables, node->varNumber()));
759         def(HeapLocation(ClosureVariableLoc, AbstractHeap(Variables, node->varNumber()), node->child2()), node->child3().node());
760         return;
761         
762     case GetGlobalVar:
763         read(AbstractHeap(Absolute, node->registerPointer()));
764         def(HeapLocation(GlobalVariableLoc, AbstractHeap(Absolute, node->registerPointer())), node);
765         return;
766         
767     case PutGlobalVar:
768         write(AbstractHeap(Absolute, node->registerPointer()));
769         def(HeapLocation(GlobalVariableLoc, AbstractHeap(Absolute, node->registerPointer())), node->child1().node());
770         return;
771
772     case NewArray:
773     case NewArrayWithSize:
774     case NewArrayBuffer:
775     case NewTypedArray:
776         // FIXME: Enable CSE for these nodes. We can't do this right now because there is no way
777         // for us to claim an index node and a value node. We could make this work if we lowered
778         // these nodes or if we had a more flexible way of def()'ing.
779         // https://bugs.webkit.org/show_bug.cgi?id=134737
780         read(HeapObjectCount);
781         write(HeapObjectCount);
782         return;
783
784     case NewObject:
785     case NewRegexp:
786     case NewStringObject:
787     case PhantomNewObject:
788     case MaterializeNewObject:
789     case NewFunctionNoCheck:
790     case NewFunction:
791     case NewFunctionExpression:
792         read(HeapObjectCount);
793         write(HeapObjectCount);
794         return;
795         
796     case RegExpExec:
797     case RegExpTest:
798         read(RegExpState);
799         write(RegExpState);
800         return;
801
802     case StringCharAt:
803         if (node->arrayMode().isOutOfBounds()) {
804             read(World);
805             write(World);
806             return;
807         }
808         def(PureValue(node));
809         return;
810         
811     case CompareEq:
812     case CompareLess:
813     case CompareLessEq:
814     case CompareGreater:
815     case CompareGreaterEq:
816         if (!node->isBinaryUseKind(UntypedUse)) {
817             def(PureValue(node));
818             return;
819         }
820         read(World);
821         write(World);
822         return;
823         
824     case ToString:
825         switch (node->child1().useKind()) {
826         case StringObjectUse:
827         case StringOrStringObjectUse:
828             // These don't def a pure value, unfortunately. I'll avoid load-eliminating these for
829             // now.
830             return;
831             
832         case CellUse:
833         case UntypedUse:
834             read(World);
835             write(World);
836             return;
837             
838         default:
839             RELEASE_ASSERT_NOT_REACHED();
840             return;
841         }
842         
843     case TearOffArguments:
844         read(Variables);
845         write(Arguments_registers);
846         return;
847         
848     case GetMyArgumentsLength:
849         read(AbstractHeap(Variables, graph.argumentsRegisterFor(node->origin.semantic)));
850         read(AbstractHeap(Variables, JSStack::ArgumentCount));
851         // FIXME: We could def() this by specifying the code origin as a kind of m_info, like we
852         // have for PureValue.
853         // https://bugs.webkit.org/show_bug.cgi?id=134797
854         return;
855         
856     case GetMyArgumentByVal:
857         read(Variables);
858         // FIXME: We could def() this by specifying the code origin as a kind of m_info, like we
859         // have for PureValue.
860         // https://bugs.webkit.org/show_bug.cgi?id=134797
861         return;
862         
863     case CheckArgumentsNotCreated:
864         read(AbstractHeap(Variables, graph.argumentsRegisterFor(node->origin.semantic)));
865         return;
866
867     case ThrowReferenceError:
868         write(SideState);
869         read(HeapObjectCount);
870         write(HeapObjectCount);
871         return;
872         
873     case CountExecution:
874     case CheckWatchdogTimer:
875         read(InternalState);
876         write(InternalState);
877         return;
878         
879     case LastNodeType:
880         RELEASE_ASSERT_NOT_REACHED();
881         return;
882     }
883     
884     RELEASE_ASSERT_NOT_REACHED();
885 }
886
887 class NoOpClobberize {
888 public:
889     NoOpClobberize() { }
890     template<typename... T>
891     void operator()(T...) const { }
892 };
893
894 class CheckClobberize {
895 public:
896     CheckClobberize()
897         : m_result(false)
898     {
899     }
900     
901     template<typename... T>
902     void operator()(T...) const { m_result = true; }
903     
904     bool result() const { return m_result; }
905     
906 private:
907     mutable bool m_result;
908 };
909
910 bool doesWrites(Graph&, Node*);
911
912 class AbstractHeapOverlaps {
913 public:
914     AbstractHeapOverlaps(AbstractHeap heap)
915         : m_heap(heap)
916         , m_result(false)
917     {
918     }
919     
920     void operator()(AbstractHeap otherHeap) const
921     {
922         if (m_result)
923             return;
924         m_result = m_heap.overlaps(otherHeap);
925     }
926     
927     bool result() const { return m_result; }
928
929 private:
930     AbstractHeap m_heap;
931     mutable bool m_result;
932 };
933
934 bool accessesOverlap(Graph&, Node*, AbstractHeap);
935 bool writesOverlap(Graph&, Node*, AbstractHeap);
936
937 bool clobbersWorld(Graph&, Node*);
938
939 // We would have used bind() for these, but because of the overlaoding that we are doing,
940 // it's quite a bit of clearer to just write this out the traditional way.
941
942 template<typename T>
943 class ReadMethodClobberize {
944 public:
945     ReadMethodClobberize(T& value)
946         : m_value(value)
947     {
948     }
949     
950     void operator()(AbstractHeap heap) const
951     {
952         m_value.read(heap);
953     }
954 private:
955     T& m_value;
956 };
957
958 template<typename T>
959 class WriteMethodClobberize {
960 public:
961     WriteMethodClobberize(T& value)
962         : m_value(value)
963     {
964     }
965     
966     void operator()(AbstractHeap heap) const
967     {
968         m_value.write(heap);
969     }
970 private:
971     T& m_value;
972 };
973
974 template<typename T>
975 class DefMethodClobberize {
976 public:
977     DefMethodClobberize(T& value)
978         : m_value(value)
979     {
980     }
981     
982     void operator()(PureValue value) const
983     {
984         m_value.def(value);
985     }
986     
987     void operator()(HeapLocation location, Node* node) const
988     {
989         m_value.def(location, node);
990     }
991
992 private:
993     T& m_value;
994 };
995
996 template<typename Adaptor>
997 void clobberize(Graph& graph, Node* node, Adaptor& adaptor)
998 {
999     ReadMethodClobberize<Adaptor> read(adaptor);
1000     WriteMethodClobberize<Adaptor> write(adaptor);
1001     DefMethodClobberize<Adaptor> def(adaptor);
1002     clobberize(graph, node, read, write, def);
1003 }
1004
1005 } } // namespace JSC::DFG
1006
1007 #endif // ENABLE(DFG_JIT)
1008
1009 #endif // DFGClobberize_h
1010