387f0f186a949386a9f79b5d215393b668857477
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGClobberize.h
1  /*
2  * Copyright (C) 2013, 2014 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, ReadFunctor& read, WriteFunctor& write, 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 StoreBarrier:
277     case StoreBarrierWithNullCheck:
278     case PutByOffsetHint:
279     case PutStructureHint:
280         write(SideState);
281         return;
282         
283     case InvalidationPoint:
284         write(SideState);
285         def(HeapLocation(InvalidationPointLoc, Watchpoint_fire), node);
286         return;
287
288     case Flush:
289         read(AbstractHeap(Variables, node->local()));
290         write(SideState);
291         return;
292
293     case VariableWatchpoint:
294     case TypedArrayWatchpoint:
295         read(Watchpoint_fire);
296         write(SideState);
297         return;
298         
299     case NotifyWrite:
300         write(Watchpoint_fire);
301         write(SideState);
302         return;
303
304     case CreateActivation:
305         read(HeapObjectCount);
306         write(HeapObjectCount);
307         write(SideState);
308         write(Watchpoint_fire);
309         return;
310         
311     case CreateArguments:
312         read(Variables);
313         read(HeapObjectCount);
314         write(HeapObjectCount);
315         write(SideState);
316         write(Watchpoint_fire);
317         return;
318
319     case FunctionReentryWatchpoint:
320         read(Watchpoint_fire);
321         return;
322
323     case ToThis:
324     case CreateThis:
325         read(MiscFields);
326         read(HeapObjectCount);
327         write(HeapObjectCount);
328         return;
329
330     case VarInjectionWatchpoint:
331         read(MiscFields);
332         def(HeapLocation(VarInjectionWatchpointLoc, MiscFields), node);
333         return;
334
335     case AllocationProfileWatchpoint:
336         read(MiscFields);
337         def(HeapLocation(AllocationProfileWatchpointLoc, MiscFields), node);
338         return;
339         
340     case IsObject:
341         read(MiscFields);
342         def(HeapLocation(IsObjectLoc, MiscFields, node->child1()), node);
343         return;
344         
345     case IsFunction:
346         read(MiscFields);
347         def(HeapLocation(IsFunctionLoc, MiscFields, node->child1()), node);
348         return;
349         
350     case TypeOf:
351         read(MiscFields);
352         def(HeapLocation(TypeOfLoc, MiscFields, node->child1()), node);
353         return;
354
355     case GetById:
356     case GetByIdFlush:
357     case PutById:
358     case PutByIdFlush:
359     case PutByIdDirect:
360     case ArrayPush:
361     case ArrayPop:
362     case Call:
363     case Construct:
364     case ProfiledCall:
365     case ProfiledConstruct:
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 GetMyScope:
748         if (graph.m_codeBlock->needsActivation()) {
749             read(AbstractHeap(Variables, JSStack::ScopeChain));
750             def(HeapLocation(VariableLoc, AbstractHeap(Variables, JSStack::ScopeChain)), node);
751         } else
752             def(PureValue(node));
753         return;
754         
755     case GetClosureRegisters:
756         read(JSEnvironmentRecord_registers);
757         def(HeapLocation(ClosureRegistersLoc, JSEnvironmentRecord_registers, node->child1()), node);
758         return;
759
760     case GetClosureVar:
761         read(AbstractHeap(Variables, node->varNumber()));
762         def(HeapLocation(ClosureVariableLoc, AbstractHeap(Variables, node->varNumber()), node->child1()), node);
763         return;
764         
765     case PutClosureVar:
766         write(AbstractHeap(Variables, node->varNumber()));
767         def(HeapLocation(ClosureVariableLoc, AbstractHeap(Variables, node->varNumber()), node->child2()), node->child3().node());
768         return;
769         
770     case GetGlobalVar:
771         read(AbstractHeap(Absolute, node->registerPointer()));
772         def(HeapLocation(GlobalVariableLoc, AbstractHeap(Absolute, node->registerPointer())), node);
773         return;
774         
775     case PutGlobalVar:
776         write(AbstractHeap(Absolute, node->registerPointer()));
777         def(HeapLocation(GlobalVariableLoc, AbstractHeap(Absolute, node->registerPointer())), node->child1().node());
778         return;
779
780     case NewArray:
781     case NewArrayWithSize:
782     case NewArrayBuffer:
783     case NewTypedArray:
784         // FIXME: Enable CSE for these nodes. We can't do this right now because there is no way
785         // for us to claim an index node and a value node. We could make this work if we lowered
786         // these nodes or if we had a more flexible way of def()'ing.
787         // https://bugs.webkit.org/show_bug.cgi?id=134737
788         read(HeapObjectCount);
789         write(HeapObjectCount);
790         return;
791
792     case NewObject:
793     case NewRegexp:
794     case NewStringObject:
795     case PhantomNewObject:
796     case MaterializeNewObject:
797     case NewFunctionNoCheck:
798     case NewFunction:
799     case NewFunctionExpression:
800         read(HeapObjectCount);
801         write(HeapObjectCount);
802         return;
803         
804     case RegExpExec:
805     case RegExpTest:
806         read(RegExpState);
807         write(RegExpState);
808         return;
809
810     case StringCharAt:
811         if (node->arrayMode().isOutOfBounds()) {
812             read(World);
813             write(World);
814             return;
815         }
816         def(PureValue(node));
817         return;
818         
819     case CompareEq:
820     case CompareLess:
821     case CompareLessEq:
822     case CompareGreater:
823     case CompareGreaterEq:
824         if (!node->isBinaryUseKind(UntypedUse)) {
825             def(PureValue(node));
826             return;
827         }
828         read(World);
829         write(World);
830         return;
831         
832     case ToString:
833         switch (node->child1().useKind()) {
834         case StringObjectUse:
835         case StringOrStringObjectUse:
836             // These don't def a pure value, unfortunately. I'll avoid load-eliminating these for
837             // now.
838             return;
839             
840         case CellUse:
841         case UntypedUse:
842             read(World);
843             write(World);
844             return;
845             
846         default:
847             RELEASE_ASSERT_NOT_REACHED();
848             return;
849         }
850
851     case TearOffActivation:
852         read(Variables);
853         write(JSEnvironmentRecord_registers);
854         return;
855         
856     case TearOffArguments:
857         read(Variables);
858         write(Arguments_registers);
859         return;
860         
861     case GetMyArgumentsLength:
862         read(AbstractHeap(Variables, graph.argumentsRegisterFor(node->origin.semantic)));
863         read(AbstractHeap(Variables, JSStack::ArgumentCount));
864         // FIXME: We could def() this by specifying the code origin as a kind of m_info, like we
865         // have for PureValue.
866         // https://bugs.webkit.org/show_bug.cgi?id=134797
867         return;
868         
869     case GetMyArgumentByVal:
870         read(Variables);
871         // FIXME: We could def() this by specifying the code origin as a kind of m_info, like we
872         // have for PureValue.
873         // https://bugs.webkit.org/show_bug.cgi?id=134797
874         return;
875         
876     case CheckArgumentsNotCreated:
877         read(AbstractHeap(Variables, graph.argumentsRegisterFor(node->origin.semantic)));
878         return;
879
880     case ThrowReferenceError:
881         write(SideState);
882         read(HeapObjectCount);
883         write(HeapObjectCount);
884         return;
885         
886     case CountExecution:
887     case CheckWatchdogTimer:
888         read(InternalState);
889         write(InternalState);
890         return;
891         
892     case LastNodeType:
893         RELEASE_ASSERT_NOT_REACHED();
894         return;
895     }
896     
897     RELEASE_ASSERT_NOT_REACHED();
898 }
899
900 class NoOpClobberize {
901 public:
902     NoOpClobberize() { }
903     template<typename... T>
904     void operator()(T...) { }
905 };
906
907 class CheckClobberize {
908 public:
909     CheckClobberize()
910         : m_result(false)
911     {
912     }
913     
914     template<typename... T>
915     void operator()(T...) { m_result = true; }
916     
917     bool result() const { return m_result; }
918     
919 private:
920     bool m_result;
921 };
922
923 bool doesWrites(Graph&, Node*);
924
925 class AbstractHeapOverlaps {
926 public:
927     AbstractHeapOverlaps(AbstractHeap heap)
928         : m_heap(heap)
929         , m_result(false)
930     {
931     }
932     
933     void operator()(AbstractHeap otherHeap)
934     {
935         if (m_result)
936             return;
937         m_result = m_heap.overlaps(otherHeap);
938     }
939     
940     bool result() const { return m_result; }
941
942 private:
943     AbstractHeap m_heap;
944     bool m_result;
945 };
946
947 bool accessesOverlap(Graph&, Node*, AbstractHeap);
948 bool writesOverlap(Graph&, Node*, AbstractHeap);
949
950 // We would have used bind() for these, but because of the overlaoding that we are doing,
951 // it's quite a bit of clearer to just write this out the traditional way.
952
953 template<typename T>
954 class ReadMethodClobberize {
955 public:
956     ReadMethodClobberize(T& value)
957         : m_value(value)
958     {
959     }
960     
961     void operator()(AbstractHeap heap)
962     {
963         m_value.read(heap);
964     }
965 private:
966     T& m_value;
967 };
968
969 template<typename T>
970 class WriteMethodClobberize {
971 public:
972     WriteMethodClobberize(T& value)
973         : m_value(value)
974     {
975     }
976     
977     void operator()(AbstractHeap heap)
978     {
979         m_value.write(heap);
980     }
981 private:
982     T& m_value;
983 };
984
985 template<typename T>
986 class DefMethodClobberize {
987 public:
988     DefMethodClobberize(T& value)
989         : m_value(value)
990     {
991     }
992     
993     void operator()(PureValue value)
994     {
995         m_value.def(value);
996     }
997     
998     void operator()(HeapLocation location, Node* node)
999     {
1000         m_value.def(location, node);
1001     }
1002
1003 private:
1004     T& m_value;
1005 };
1006
1007 template<typename Adaptor>
1008 void clobberize(Graph& graph, Node* node, Adaptor& adaptor)
1009 {
1010     ReadMethodClobberize<Adaptor> read(adaptor);
1011     WriteMethodClobberize<Adaptor> write(adaptor);
1012     DefMethodClobberize<Adaptor> def(adaptor);
1013     clobberize(graph, node, read, write, def);
1014 }
1015
1016 } } // namespace JSC::DFG
1017
1018 #endif // ENABLE(DFG_JIT)
1019
1020 #endif // DFGClobberize_h
1021