ed2042a2f4985a8843f52728c17d50e8adaf061a
[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, 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 StoreBarrier:
278     case StoreBarrierWithNullCheck:
279     case PutByOffsetHint:
280     case PutStructureHint:
281         write(SideState);
282         return;
283         
284     case InvalidationPoint:
285         write(SideState);
286         def(HeapLocation(InvalidationPointLoc, Watchpoint_fire), node);
287         return;
288
289     case Flush:
290         read(AbstractHeap(Variables, node->local()));
291         write(SideState);
292         return;
293
294     case VariableWatchpoint:
295     case TypedArrayWatchpoint:
296         read(Watchpoint_fire);
297         write(SideState);
298         return;
299         
300     case NotifyWrite:
301         write(Watchpoint_fire);
302         write(SideState);
303         return;
304
305     case CreateActivation:
306         read(HeapObjectCount);
307         write(HeapObjectCount);
308         write(SideState);
309         write(Watchpoint_fire);
310         return;
311         
312     case CreateArguments:
313         read(Variables);
314         read(HeapObjectCount);
315         write(HeapObjectCount);
316         write(SideState);
317         write(Watchpoint_fire);
318         return;
319
320     case FunctionReentryWatchpoint:
321         read(Watchpoint_fire);
322         return;
323
324     case ToThis:
325     case CreateThis:
326         read(MiscFields);
327         read(HeapObjectCount);
328         write(HeapObjectCount);
329         return;
330
331     case VarInjectionWatchpoint:
332         read(MiscFields);
333         def(HeapLocation(VarInjectionWatchpointLoc, MiscFields), node);
334         return;
335
336     case AllocationProfileWatchpoint:
337         read(MiscFields);
338         def(HeapLocation(AllocationProfileWatchpointLoc, MiscFields), node);
339         return;
340         
341     case IsObject:
342         read(MiscFields);
343         def(HeapLocation(IsObjectLoc, MiscFields, node->child1()), node);
344         return;
345         
346     case IsFunction:
347         read(MiscFields);
348         def(HeapLocation(IsFunctionLoc, MiscFields, node->child1()), node);
349         return;
350         
351     case TypeOf:
352         read(MiscFields);
353         def(HeapLocation(TypeOfLoc, MiscFields, node->child1()), node);
354         return;
355
356     case GetById:
357     case GetByIdFlush:
358     case PutById:
359     case PutByIdFlush:
360     case PutByIdDirect:
361     case ArrayPush:
362     case ArrayPop:
363     case Call:
364     case Construct:
365     case ProfiledCall:
366     case ProfiledConstruct:
367     case NativeCall:
368     case NativeConstruct:
369     case ToPrimitive:
370     case In:
371     case GetMyArgumentsLengthSafe:
372     case GetMyArgumentByValSafe:
373     case ValueAdd:
374         read(World);
375         write(World);
376         return;
377         
378     case GetGetter:
379         read(GetterSetter_getter);
380         def(HeapLocation(GetterLoc, GetterSetter_getter, node->child1()), node);
381         return;
382         
383     case GetSetter:
384         read(GetterSetter_setter);
385         def(HeapLocation(SetterLoc, GetterSetter_setter, node->child1()), node);
386         return;
387         
388     case GetCallee:
389         read(AbstractHeap(Variables, JSStack::Callee));
390         def(HeapLocation(VariableLoc, AbstractHeap(Variables, JSStack::Callee)), node);
391         return;
392         
393     case GetLocal:
394     case GetArgument:
395         read(AbstractHeap(Variables, node->local()));
396         def(HeapLocation(VariableLoc, AbstractHeap(Variables, node->local())), node);
397         return;
398         
399     case SetLocal:
400     case PutLocal:
401         write(AbstractHeap(Variables, node->local()));
402         def(HeapLocation(VariableLoc, AbstractHeap(Variables, node->local())), node->child1().node());
403         return;
404         
405     case GetLocalUnlinked:
406         read(AbstractHeap(Variables, node->unlinkedLocal()));
407         def(HeapLocation(VariableLoc, AbstractHeap(Variables, node->unlinkedLocal())), node);
408         return;
409         
410     case GetByVal: {
411         ArrayMode mode = node->arrayMode();
412         switch (mode.type()) {
413         case Array::SelectUsingPredictions:
414         case Array::Unprofiled:
415         case Array::Undecided:
416             // Assume the worst since we don't have profiling yet.
417             read(World);
418             write(World);
419             return;
420             
421         case Array::ForceExit:
422             write(SideState);
423             return;
424             
425         case Array::Generic:
426             read(World);
427             write(World);
428             return;
429             
430         case Array::String:
431             if (mode.isOutOfBounds()) {
432                 read(World);
433                 write(World);
434                 return;
435             }
436             // This appears to read nothing because it's only reading immutable data.
437             def(PureValue(node, mode.asWord()));
438             return;
439             
440         case Array::Arguments:
441             read(Arguments_registers);
442             read(Variables);
443             def(HeapLocation(IndexedPropertyLoc, Variables, node->child1(), node->child2()), node);
444             return;
445             
446         case Array::Int32:
447             if (mode.isInBounds()) {
448                 read(Butterfly_publicLength);
449                 read(IndexedInt32Properties);
450                 def(HeapLocation(IndexedPropertyLoc, IndexedInt32Properties, node->child1(), node->child2()), node);
451                 return;
452             }
453             read(World);
454             write(World);
455             return;
456             
457         case Array::Double:
458             if (mode.isInBounds()) {
459                 read(Butterfly_publicLength);
460                 read(IndexedDoubleProperties);
461                 def(HeapLocation(IndexedPropertyLoc, IndexedDoubleProperties, node->child1(), node->child2()), node);
462                 return;
463             }
464             read(World);
465             write(World);
466             return;
467             
468         case Array::Contiguous:
469             if (mode.isInBounds()) {
470                 read(Butterfly_publicLength);
471                 read(IndexedContiguousProperties);
472                 def(HeapLocation(IndexedPropertyLoc, IndexedContiguousProperties, node->child1(), node->child2()), node);
473                 return;
474             }
475             read(World);
476             write(World);
477             return;
478             
479         case Array::ArrayStorage:
480         case Array::SlowPutArrayStorage:
481             if (mode.isInBounds()) {
482                 read(Butterfly_vectorLength);
483                 read(IndexedArrayStorageProperties);
484                 return;
485             }
486             read(World);
487             write(World);
488             return;
489             
490         case Array::Int8Array:
491         case Array::Int16Array:
492         case Array::Int32Array:
493         case Array::Uint8Array:
494         case Array::Uint8ClampedArray:
495         case Array::Uint16Array:
496         case Array::Uint32Array:
497         case Array::Float32Array:
498         case Array::Float64Array:
499             read(TypedArrayProperties);
500             read(MiscFields);
501             def(HeapLocation(IndexedPropertyLoc, TypedArrayProperties, node->child1(), node->child2()), node);
502             return;
503         }
504         RELEASE_ASSERT_NOT_REACHED();
505         return;
506     }
507
508     case PutByValDirect:
509     case PutByVal:
510     case PutByValAlias: {
511         ArrayMode mode = node->arrayMode();
512         Node* base = graph.varArgChild(node, 0).node();
513         Node* index = graph.varArgChild(node, 1).node();
514         Node* value = graph.varArgChild(node, 2).node();
515         switch (mode.modeForPut().type()) {
516         case Array::SelectUsingPredictions:
517         case Array::Unprofiled:
518         case Array::Undecided:
519         case Array::String:
520             // Assume the worst since we don't have profiling yet.
521             read(World);
522             write(World);
523             return;
524             
525         case Array::ForceExit:
526             write(SideState);
527             return;
528             
529         case Array::Generic:
530             read(World);
531             write(World);
532             return;
533             
534         case Array::Arguments:
535             read(Arguments_registers);
536             read(MiscFields);
537             write(Variables);
538             def(HeapLocation(IndexedPropertyLoc, Variables, base, index), value);
539             return;
540             
541         case Array::Int32:
542             if (node->arrayMode().isOutOfBounds()) {
543                 read(World);
544                 write(World);
545                 return;
546             }
547             read(Butterfly_publicLength);
548             read(Butterfly_vectorLength);
549             read(IndexedInt32Properties);
550             write(IndexedInt32Properties);
551             if (node->arrayMode().mayStoreToHole())
552                 write(Butterfly_publicLength);
553             def(HeapLocation(IndexedPropertyLoc, IndexedInt32Properties, base, index), value);
554             return;
555             
556         case Array::Double:
557             if (node->arrayMode().isOutOfBounds()) {
558                 read(World);
559                 write(World);
560                 return;
561             }
562             read(Butterfly_publicLength);
563             read(Butterfly_vectorLength);
564             read(IndexedDoubleProperties);
565             write(IndexedDoubleProperties);
566             if (node->arrayMode().mayStoreToHole())
567                 write(Butterfly_publicLength);
568             def(HeapLocation(IndexedPropertyLoc, IndexedDoubleProperties, base, index), value);
569             return;
570             
571         case Array::Contiguous:
572             if (node->arrayMode().isOutOfBounds()) {
573                 read(World);
574                 write(World);
575                 return;
576             }
577             read(Butterfly_publicLength);
578             read(Butterfly_vectorLength);
579             read(IndexedContiguousProperties);
580             write(IndexedContiguousProperties);
581             if (node->arrayMode().mayStoreToHole())
582                 write(Butterfly_publicLength);
583             def(HeapLocation(IndexedPropertyLoc, IndexedContiguousProperties, base, index), value);
584             return;
585             
586         case Array::ArrayStorage:
587         case Array::SlowPutArrayStorage:
588             // Give up on life for now.
589             read(World);
590             write(World);
591             return;
592
593         case Array::Int8Array:
594         case Array::Int16Array:
595         case Array::Int32Array:
596         case Array::Uint8Array:
597         case Array::Uint8ClampedArray:
598         case Array::Uint16Array:
599         case Array::Uint32Array:
600         case Array::Float32Array:
601         case Array::Float64Array:
602             read(MiscFields);
603             write(TypedArrayProperties);
604             // FIXME: We can't def() anything here because these operations truncate their inputs.
605             // https://bugs.webkit.org/show_bug.cgi?id=134737
606             return;
607         }
608         RELEASE_ASSERT_NOT_REACHED();
609         return;
610     }
611         
612     case CheckStructure:
613         read(JSCell_structureID);
614         return;
615
616     case CheckArray:
617         read(JSCell_indexingType);
618         read(JSCell_typeInfoType);
619         read(JSCell_structureID);
620         return;
621
622     case CheckHasInstance:
623         read(JSCell_typeInfoFlags);
624         def(HeapLocation(CheckHasInstanceLoc, JSCell_typeInfoFlags, node->child1()), node);
625         return;
626
627     case InstanceOf:
628         read(JSCell_structureID);
629         def(HeapLocation(InstanceOfLoc, JSCell_structureID, node->child1(), node->child2()), node);
630         return;
631
632     case PutStructure:
633         write(JSCell_structureID);
634         write(JSCell_typeInfoType);
635         write(JSCell_typeInfoFlags);
636         write(JSCell_indexingType);
637         return;
638         
639     case AllocatePropertyStorage:
640         write(JSObject_butterfly);
641         def(HeapLocation(ButterflyLoc, JSObject_butterfly, node->child1()), node);
642         return;
643         
644     case ReallocatePropertyStorage:
645         read(JSObject_butterfly);
646         write(JSObject_butterfly);
647         def(HeapLocation(ButterflyLoc, JSObject_butterfly, node->child1()), node);
648         return;
649         
650     case GetButterfly:
651         read(JSObject_butterfly);
652         def(HeapLocation(ButterflyLoc, JSObject_butterfly, node->child1()), node);
653         return;
654         
655     case Arrayify:
656     case ArrayifyToStructure:
657         read(JSCell_structureID);
658         read(JSCell_indexingType);
659         read(JSObject_butterfly);
660         write(JSCell_structureID);
661         write(JSCell_indexingType);
662         write(JSObject_butterfly);
663         write(Watchpoint_fire);
664         return;
665         
666     case GetIndexedPropertyStorage:
667         if (node->arrayMode().type() == Array::String) {
668             def(PureValue(node, node->arrayMode().asWord()));
669             return;
670         }
671         read(MiscFields);
672         def(HeapLocation(IndexedPropertyStorageLoc, MiscFields, node->child1()), node);
673         return;
674         
675     case GetTypedArrayByteOffset:
676         read(MiscFields);
677         def(HeapLocation(TypedArrayByteOffsetLoc, MiscFields, node->child1()), node);
678         return;
679         
680     case GetByOffset:
681     case GetGetterSetterByOffset: {
682         unsigned identifierNumber = node->storageAccessData().identifierNumber;
683         AbstractHeap heap(NamedProperties, identifierNumber);
684         read(heap);
685         def(HeapLocation(NamedPropertyLoc, heap, node->child2()), node);
686         return;
687     }
688         
689     case MultiGetByOffset: {
690         read(JSCell_structureID);
691         read(JSObject_butterfly);
692         AbstractHeap heap(NamedProperties, node->multiGetByOffsetData().identifierNumber);
693         read(heap);
694         def(HeapLocation(NamedPropertyLoc, heap, node->child1()), node);
695         return;
696     }
697         
698     case MultiPutByOffset: {
699         read(JSCell_structureID);
700         read(JSObject_butterfly);
701         AbstractHeap heap(NamedProperties, node->multiPutByOffsetData().identifierNumber);
702         write(heap);
703         if (node->multiPutByOffsetData().writesStructures())
704             write(JSCell_structureID);
705         if (node->multiPutByOffsetData().reallocatesStorage())
706             write(JSObject_butterfly);
707         def(HeapLocation(NamedPropertyLoc, heap, node->child1()), node->child2().node());
708         return;
709     }
710         
711     case PutByOffset: {
712         unsigned identifierNumber = node->storageAccessData().identifierNumber;
713         AbstractHeap heap(NamedProperties, identifierNumber);
714         write(heap);
715         def(HeapLocation(NamedPropertyLoc, heap, node->child2()), node->child3().node());
716         return;
717     }
718         
719     case GetArrayLength: {
720         ArrayMode mode = node->arrayMode();
721         switch (mode.type()) {
722         case Array::Int32:
723         case Array::Double:
724         case Array::Contiguous:
725         case Array::ArrayStorage:
726         case Array::SlowPutArrayStorage:
727             read(Butterfly_publicLength);
728             def(HeapLocation(ArrayLengthLoc, Butterfly_publicLength, node->child1()), node);
729             return;
730             
731         case Array::String:
732             def(PureValue(node, mode.asWord()));
733             return;
734             
735         case Array::Arguments:
736             read(MiscFields);
737             def(HeapLocation(ArrayLengthLoc, MiscFields, node->child1()), node);
738             return;
739             
740         default:
741             ASSERT(mode.typedArrayType() != NotTypedArray);
742             read(MiscFields);
743             def(HeapLocation(ArrayLengthLoc, MiscFields, node->child1()), node);
744             return;
745         }
746     }
747         
748     case GetMyScope:
749         if (graph.m_codeBlock->needsActivation()) {
750             read(AbstractHeap(Variables, JSStack::ScopeChain));
751             def(HeapLocation(VariableLoc, AbstractHeap(Variables, JSStack::ScopeChain)), node);
752         } else
753             def(PureValue(node));
754         return;
755         
756     case GetClosureRegisters:
757         read(JSEnvironmentRecord_registers);
758         def(HeapLocation(ClosureRegistersLoc, JSEnvironmentRecord_registers, node->child1()), node);
759         return;
760
761     case GetClosureVar:
762         read(AbstractHeap(Variables, node->varNumber()));
763         def(HeapLocation(ClosureVariableLoc, AbstractHeap(Variables, node->varNumber()), node->child1()), node);
764         return;
765         
766     case PutClosureVar:
767         write(AbstractHeap(Variables, node->varNumber()));
768         def(HeapLocation(ClosureVariableLoc, AbstractHeap(Variables, node->varNumber()), node->child2()), node->child3().node());
769         return;
770         
771     case GetGlobalVar:
772         read(AbstractHeap(Absolute, node->registerPointer()));
773         def(HeapLocation(GlobalVariableLoc, AbstractHeap(Absolute, node->registerPointer())), node);
774         return;
775         
776     case PutGlobalVar:
777         write(AbstractHeap(Absolute, node->registerPointer()));
778         def(HeapLocation(GlobalVariableLoc, AbstractHeap(Absolute, node->registerPointer())), node->child1().node());
779         return;
780
781     case NewArray:
782     case NewArrayWithSize:
783     case NewArrayBuffer:
784     case NewTypedArray:
785         // FIXME: Enable CSE for these nodes. We can't do this right now because there is no way
786         // for us to claim an index node and a value node. We could make this work if we lowered
787         // these nodes or if we had a more flexible way of def()'ing.
788         // https://bugs.webkit.org/show_bug.cgi?id=134737
789         read(HeapObjectCount);
790         write(HeapObjectCount);
791         return;
792
793     case NewObject:
794     case NewRegexp:
795     case NewStringObject:
796     case PhantomNewObject:
797     case MaterializeNewObject:
798     case NewFunctionNoCheck:
799     case NewFunction:
800     case NewFunctionExpression:
801         read(HeapObjectCount);
802         write(HeapObjectCount);
803         return;
804         
805     case RegExpExec:
806     case RegExpTest:
807         read(RegExpState);
808         write(RegExpState);
809         return;
810
811     case StringCharAt:
812         if (node->arrayMode().isOutOfBounds()) {
813             read(World);
814             write(World);
815             return;
816         }
817         def(PureValue(node));
818         return;
819         
820     case CompareEq:
821     case CompareLess:
822     case CompareLessEq:
823     case CompareGreater:
824     case CompareGreaterEq:
825         if (!node->isBinaryUseKind(UntypedUse)) {
826             def(PureValue(node));
827             return;
828         }
829         read(World);
830         write(World);
831         return;
832         
833     case ToString:
834         switch (node->child1().useKind()) {
835         case StringObjectUse:
836         case StringOrStringObjectUse:
837             // These don't def a pure value, unfortunately. I'll avoid load-eliminating these for
838             // now.
839             return;
840             
841         case CellUse:
842         case UntypedUse:
843             read(World);
844             write(World);
845             return;
846             
847         default:
848             RELEASE_ASSERT_NOT_REACHED();
849             return;
850         }
851         
852     case TearOffArguments:
853         read(Variables);
854         write(Arguments_registers);
855         return;
856         
857     case GetMyArgumentsLength:
858         read(AbstractHeap(Variables, graph.argumentsRegisterFor(node->origin.semantic)));
859         read(AbstractHeap(Variables, JSStack::ArgumentCount));
860         // FIXME: We could def() this by specifying the code origin as a kind of m_info, like we
861         // have for PureValue.
862         // https://bugs.webkit.org/show_bug.cgi?id=134797
863         return;
864         
865     case GetMyArgumentByVal:
866         read(Variables);
867         // FIXME: We could def() this by specifying the code origin as a kind of m_info, like we
868         // have for PureValue.
869         // https://bugs.webkit.org/show_bug.cgi?id=134797
870         return;
871         
872     case CheckArgumentsNotCreated:
873         read(AbstractHeap(Variables, graph.argumentsRegisterFor(node->origin.semantic)));
874         return;
875
876     case ThrowReferenceError:
877         write(SideState);
878         read(HeapObjectCount);
879         write(HeapObjectCount);
880         return;
881         
882     case CountExecution:
883     case CheckWatchdogTimer:
884         read(InternalState);
885         write(InternalState);
886         return;
887         
888     case LastNodeType:
889         RELEASE_ASSERT_NOT_REACHED();
890         return;
891     }
892     
893     RELEASE_ASSERT_NOT_REACHED();
894 }
895
896 class NoOpClobberize {
897 public:
898     NoOpClobberize() { }
899     template<typename... T>
900     void operator()(T...) const { }
901 };
902
903 class CheckClobberize {
904 public:
905     CheckClobberize()
906         : m_result(false)
907     {
908     }
909     
910     template<typename... T>
911     void operator()(T...) const { m_result = true; }
912     
913     bool result() const { return m_result; }
914     
915 private:
916     mutable bool m_result;
917 };
918
919 bool doesWrites(Graph&, Node*);
920
921 class AbstractHeapOverlaps {
922 public:
923     AbstractHeapOverlaps(AbstractHeap heap)
924         : m_heap(heap)
925         , m_result(false)
926     {
927     }
928     
929     void operator()(AbstractHeap otherHeap) const
930     {
931         if (m_result)
932             return;
933         m_result = m_heap.overlaps(otherHeap);
934     }
935     
936     bool result() const { return m_result; }
937
938 private:
939     AbstractHeap m_heap;
940     mutable bool m_result;
941 };
942
943 bool accessesOverlap(Graph&, Node*, AbstractHeap);
944 bool writesOverlap(Graph&, Node*, AbstractHeap);
945
946 // We would have used bind() for these, but because of the overlaoding that we are doing,
947 // it's quite a bit of clearer to just write this out the traditional way.
948
949 template<typename T>
950 class ReadMethodClobberize {
951 public:
952     ReadMethodClobberize(T& value)
953         : m_value(value)
954     {
955     }
956     
957     void operator()(AbstractHeap heap) const
958     {
959         m_value.read(heap);
960     }
961 private:
962     T& m_value;
963 };
964
965 template<typename T>
966 class WriteMethodClobberize {
967 public:
968     WriteMethodClobberize(T& value)
969         : m_value(value)
970     {
971     }
972     
973     void operator()(AbstractHeap heap) const
974     {
975         m_value.write(heap);
976     }
977 private:
978     T& m_value;
979 };
980
981 template<typename T>
982 class DefMethodClobberize {
983 public:
984     DefMethodClobberize(T& value)
985         : m_value(value)
986     {
987     }
988     
989     void operator()(PureValue value) const
990     {
991         m_value.def(value);
992     }
993     
994     void operator()(HeapLocation location, Node* node) const
995     {
996         m_value.def(location, node);
997     }
998
999 private:
1000     T& m_value;
1001 };
1002
1003 template<typename Adaptor>
1004 void clobberize(Graph& graph, Node* node, Adaptor& adaptor)
1005 {
1006     ReadMethodClobberize<Adaptor> read(adaptor);
1007     WriteMethodClobberize<Adaptor> write(adaptor);
1008     DefMethodClobberize<Adaptor> def(adaptor);
1009     clobberize(graph, node, read, write, def);
1010 }
1011
1012 } } // namespace JSC::DFG
1013
1014 #endif // ENABLE(DFG_JIT)
1015
1016 #endif // DFGClobberize_h
1017