1/*
2 * Copyright (C) 2013-2018 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#pragma once
27
28#if ENABLE(DFG_JIT)
29
30#include "DFGAbstractHeap.h"
31#include "DFGGraph.h"
32#include "DFGHeapLocation.h"
33#include "DFGLazyNode.h"
34#include "DFGPureValue.h"
35#include "DOMJITCallDOMGetterSnippet.h"
36#include "DOMJITSignature.h"
37#include "InlineCallFrame.h"
38#include "JSFixedArray.h"
39#include "JSImmutableButterfly.h"
40
41namespace JSC { namespace DFG {
42
43template<typename ReadFunctor, typename WriteFunctor, typename DefFunctor>
44void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFunctor& write, const DefFunctor& def)
45{
46 // Some notes:
47 //
48 // - The canonical way of clobbering the world is to read world and write
49 // heap. This is because World subsumes Heap and Stack, and Stack can be
50 // read by anyone but only written to by explicit stack writing operations.
51 // Of course, claiming to also write World is not wrong; it'll just
52 // pessimise some important optimizations.
53 //
54 // - We cannot hoist, or sink, anything that has effects. This means that the
55 // easiest way of indicating that something cannot be hoisted is to claim
56 // that it side-effects some miscellaneous thing.
57 //
58 // - We cannot hoist forward-exiting nodes without some additional effort. I
59 // believe that what it comes down to is that forward-exiting generally have
60 // their NodeExitsForward cleared upon hoist, except for forward-exiting
61 // nodes that take bogus state as their input. Those are substantially
62 // harder. We disable it for now. In the future we could enable it by having
63 // versions of those nodes that backward-exit instead, but I'm not convinced
64 // of the soundness.
65 //
66 // - Some nodes lie, and claim that they do not read the JSCell_structureID,
67 // JSCell_typeInfoFlags, etc. These are nodes that use the structure in a way
68 // that does not depend on things that change under structure transitions.
69 //
70 // - It's implicitly understood that OSR exits read the world. This is why we
71 // generally don't move or eliminate stores. Every node can exit, so the
72 // read set does not reflect things that would be read if we exited.
73 // Instead, the read set reflects what the node will have to read if it
74 // *doesn't* exit.
75 //
76 // - Broadly, we don't say that we're reading something if that something is
77 // immutable.
78 //
79 // - This must be sound even prior to type inference. We use this as early as
80 // bytecode parsing to determine at which points in the program it's legal to
81 // OSR exit.
82 //
83 // - If you do read(Stack) or read(World), then make sure that readTop() in
84 // PreciseLocalClobberize is correct.
85
86 // While read() and write() are fairly self-explanatory - they track what sorts of things the
87 // node may read or write - the def() functor is more tricky. It tells you the heap locations
88 // (not just abstract heaps) that are defined by a node. A heap location comprises an abstract
89 // heap, some nodes, and a LocationKind. Briefly, a location defined by a node is a location
90 // whose value can be deduced from looking at the node itself. The locations returned must obey
91 // the following properties:
92 //
93 // - If someone wants to CSE a load from the heap, then a HeapLocation object should be
94 // sufficient to find a single matching node.
95 //
96 // - The abstract heap is the only abstract heap that could be clobbered to invalidate any such
97 // CSE attempt. I.e. if clobberize() reports that on every path between some node and a node
98 // that defines a HeapLocation that it wanted, there were no writes to any abstract heap that
99 // overlap the location's heap, then we have a sound match. Effectively, the semantics of
100 // write() and def() are intertwined such that for them to be sound they must agree on what
101 // is CSEable.
102 //
103 // read(), write(), and def() for heap locations is enough to do GCSE on effectful things. To
104 // keep things simple, this code will also def() pure things. def() must be overloaded to also
105 // accept PureValue. This way, a client of clobberize() can implement GCSE entirely using the
106 // information that clobberize() passes to write() and def(). Other clients of clobberize() can
107 // just ignore def() by using a NoOpClobberize functor.
108
109 // We allow the runtime to perform a stack scan at any time. We don't model which nodes get implemented
110 // by calls into the runtime. For debugging we might replace the implementation of any node with a call
111 // to the runtime, and that call may walk stack. Therefore, each node must read() anything that a stack
112 // scan would read. That's what this does.
113 for (InlineCallFrame* inlineCallFrame = node->origin.semantic.inlineCallFrame(); inlineCallFrame; inlineCallFrame = inlineCallFrame->directCaller.inlineCallFrame()) {
114 if (inlineCallFrame->isClosureCall)
115 read(AbstractHeap(Stack, inlineCallFrame->stackOffset + CallFrameSlot::callee));
116 if (inlineCallFrame->isVarargs())
117 read(AbstractHeap(Stack, inlineCallFrame->stackOffset + CallFrameSlot::argumentCount));
118 }
119
120 // We don't want to specifically account which nodes can read from the scope
121 // when the debugger is enabled. It's helpful to just claim all nodes do.
122 // Specifically, if a node allocates, this may call into the debugger's machinery.
123 // The debugger's machinery is free to take a stack trace and try to read from
124 // a scope which is expected to be flushed to the stack.
125 if (graph.hasDebuggerEnabled()) {
126 ASSERT(!node->origin.semantic.inlineCallFrame());
127 read(AbstractHeap(Stack, graph.m_codeBlock->scopeRegister()));
128 }
129
130 switch (node->op()) {
131 case JSConstant:
132 case DoubleConstant:
133 case Int52Constant:
134 def(PureValue(node, node->constant()));
135 return;
136
137 case Identity:
138 case IdentityWithProfile:
139 case Phantom:
140 case Check:
141 case CheckVarargs:
142 case ExtractOSREntryLocal:
143 case CheckStructureImmediate:
144 return;
145
146 case ExtractCatchLocal:
147 read(AbstractHeap(CatchLocals, node->catchOSREntryIndex()));
148 return;
149
150 case ClearCatchLocals:
151 write(CatchLocals);
152 return;
153
154 case LazyJSConstant:
155 // We should enable CSE of LazyJSConstant. It's a little annoying since LazyJSValue has
156 // more bits than we currently have in PureValue.
157 return;
158
159 case CompareEqPtr:
160 def(PureValue(node, node->cellOperand()->cell()));
161 return;
162
163 case ArithIMul:
164 case ArithMin:
165 case ArithMax:
166 case ArithPow:
167 case GetScope:
168 case SkipScope:
169 case GetGlobalObject:
170 case StringCharCodeAt:
171 case CompareStrictEq:
172 case SameValue:
173 case IsEmpty:
174 case IsUndefined:
175 case IsUndefinedOrNull:
176 case IsBoolean:
177 case IsNumber:
178 case NumberIsInteger:
179 case IsObject:
180 case IsTypedArrayView:
181 case LogicalNot:
182 case CheckInBounds:
183 case DoubleRep:
184 case ValueRep:
185 case Int52Rep:
186 case BooleanToNumber:
187 case FiatInt52:
188 case MakeRope:
189 case StrCat:
190 case ValueToInt32:
191 case GetExecutable:
192 case BottomValue:
193 case TypeOf:
194 def(PureValue(node));
195 return;
196
197 case GetGlobalThis:
198 read(World);
199 return;
200
201 case AtomicsIsLockFree:
202 if (node->child1().useKind() == Int32Use)
203 def(PureValue(node));
204 else {
205 read(World);
206 write(Heap);
207 }
208 return;
209
210 case ArithUnary:
211 if (node->child1().useKind() == DoubleRepUse)
212 def(PureValue(node, static_cast<std::underlying_type<Arith::UnaryType>::type>(node->arithUnaryType())));
213 else {
214 read(World);
215 write(Heap);
216 }
217 return;
218
219 case ArithFRound:
220 case ArithSqrt:
221 if (node->child1().useKind() == DoubleRepUse)
222 def(PureValue(node));
223 else {
224 read(World);
225 write(Heap);
226 }
227 return;
228
229 case ArithAbs:
230 if (node->child1().useKind() == Int32Use || node->child1().useKind() == DoubleRepUse)
231 def(PureValue(node));
232 else {
233 read(World);
234 write(Heap);
235 }
236 return;
237
238 case ArithClz32:
239 if (node->child1().useKind() == Int32Use || node->child1().useKind() == KnownInt32Use)
240 def(PureValue(node));
241 else {
242 read(World);
243 write(Heap);
244 }
245 return;
246
247 case ArithNegate:
248 if (node->child1().useKind() == Int32Use
249 || node->child1().useKind() == DoubleRepUse
250 || node->child1().useKind() == Int52RepUse)
251 def(PureValue(node));
252 else {
253 read(World);
254 write(Heap);
255 }
256 return;
257
258 case IsCellWithType:
259 def(PureValue(node, node->queriedType()));
260 return;
261
262 case ValueBitNot:
263 if (node->child1().useKind() == BigIntUse) {
264 def(PureValue(node));
265 return;
266 }
267 read(World);
268 write(Heap);
269 return;
270
271 case ArithBitNot:
272 if (node->child1().useKind() == UntypedUse) {
273 read(World);
274 write(Heap);
275 return;
276 }
277 def(PureValue(node));
278 return;
279
280 case ArithBitAnd:
281 case ArithBitOr:
282 case ArithBitXor:
283 case BitLShift:
284 case BitRShift:
285 case BitURShift:
286 if (node->child1().useKind() == UntypedUse || node->child2().useKind() == UntypedUse) {
287 read(World);
288 write(Heap);
289 return;
290 }
291 def(PureValue(node));
292 return;
293
294 case ArithRandom:
295 read(MathDotRandomState);
296 write(MathDotRandomState);
297 return;
298
299 case GetEnumerableLength: {
300 read(Heap);
301 write(SideState);
302 return;
303 }
304
305 case ToIndexString:
306 case GetEnumeratorStructurePname:
307 case GetEnumeratorGenericPname: {
308 def(PureValue(node));
309 return;
310 }
311
312 case HasIndexedProperty: {
313 read(JSObject_butterfly);
314 ArrayMode mode = node->arrayMode();
315 switch (mode.type()) {
316 case Array::ForceExit: {
317 write(SideState);
318 return;
319 }
320 case Array::Int32: {
321 if (mode.isInBounds()) {
322 read(Butterfly_publicLength);
323 read(IndexedInt32Properties);
324 def(HeapLocation(HasIndexedPropertyLoc, IndexedInt32Properties, graph.varArgChild(node, 0), graph.varArgChild(node, 1)), LazyNode(node));
325 return;
326 }
327 read(Heap);
328 return;
329 }
330
331 case Array::Double: {
332 if (mode.isInBounds()) {
333 read(Butterfly_publicLength);
334 read(IndexedDoubleProperties);
335 def(HeapLocation(HasIndexedPropertyLoc, IndexedDoubleProperties, graph.varArgChild(node, 0), graph.varArgChild(node, 1)), LazyNode(node));
336 return;
337 }
338 read(Heap);
339 return;
340 }
341
342 case Array::Contiguous: {
343 if (mode.isInBounds()) {
344 read(Butterfly_publicLength);
345 read(IndexedContiguousProperties);
346 def(HeapLocation(HasIndexedPropertyLoc, IndexedContiguousProperties, graph.varArgChild(node, 0), graph.varArgChild(node, 1)), LazyNode(node));
347 return;
348 }
349 read(Heap);
350 return;
351 }
352
353 case Array::ArrayStorage: {
354 if (mode.isInBounds()) {
355 read(Butterfly_vectorLength);
356 read(IndexedArrayStorageProperties);
357 return;
358 }
359 read(Heap);
360 return;
361 }
362
363 default: {
364 read(World);
365 write(Heap);
366 return;
367 }
368 }
369 RELEASE_ASSERT_NOT_REACHED();
370 return;
371 }
372
373 case StringFromCharCode:
374 switch (node->child1().useKind()) {
375 case Int32Use:
376 def(PureValue(node));
377 return;
378 case UntypedUse:
379 read(World);
380 write(Heap);
381 return;
382 default:
383 DFG_CRASH(graph, node, "Bad use kind");
384 }
385 return;
386
387 case ArithAdd:
388 case ArithMod:
389 case DoubleAsInt32:
390 case UInt32ToNumber:
391 def(PureValue(node, node->arithMode()));
392 return;
393
394 case ArithDiv:
395 case ArithMul:
396 case ArithSub:
397 switch (node->binaryUseKind()) {
398 case Int32Use:
399 case Int52RepUse:
400 case DoubleRepUse:
401 def(PureValue(node, node->arithMode()));
402 return;
403 case UntypedUse:
404 read(World);
405 write(Heap);
406 return;
407 default:
408 DFG_CRASH(graph, node, "Bad use kind");
409 }
410
411 case ArithRound:
412 case ArithFloor:
413 case ArithCeil:
414 case ArithTrunc:
415 if (node->child1().useKind() == DoubleRepUse)
416 def(PureValue(node, static_cast<uintptr_t>(node->arithRoundingMode())));
417 else {
418 read(World);
419 write(Heap);
420 }
421 return;
422
423 case CheckCell:
424 def(PureValue(CheckCell, AdjacencyList(AdjacencyList::Fixed, node->child1()), node->cellOperand()));
425 return;
426
427 case CheckNotEmpty:
428 def(PureValue(CheckNotEmpty, AdjacencyList(AdjacencyList::Fixed, node->child1())));
429 return;
430
431 case AssertNotEmpty:
432 write(SideState);
433 return;
434
435 case CheckStringIdent:
436 def(PureValue(CheckStringIdent, AdjacencyList(AdjacencyList::Fixed, node->child1()), node->uidOperand()));
437 return;
438
439 case ConstantStoragePointer:
440 def(PureValue(node, node->storagePointer()));
441 return;
442
443 case KillStack:
444 write(AbstractHeap(Stack, node->unlinkedLocal()));
445 return;
446
447 case MovHint:
448 case ZombieHint:
449 case ExitOK:
450 case Upsilon:
451 case Phi:
452 case PhantomLocal:
453 case SetArgumentDefinitely:
454 case SetArgumentMaybe:
455 case Jump:
456 case Branch:
457 case Switch:
458 case EntrySwitch:
459 case ForceOSRExit:
460 case CPUIntrinsic:
461 case CheckBadCell:
462 case Return:
463 case Unreachable:
464 case CheckTierUpInLoop:
465 case CheckTierUpAtReturn:
466 case CheckTierUpAndOSREnter:
467 case LoopHint:
468 case ProfileType:
469 case ProfileControlFlow:
470 case PutHint:
471 case InitializeEntrypointArguments:
472 case FilterCallLinkStatus:
473 case FilterGetByIdStatus:
474 case FilterPutByIdStatus:
475 case FilterInByIdStatus:
476 write(SideState);
477 return;
478
479 case StoreBarrier:
480 read(JSCell_cellState);
481 write(JSCell_cellState);
482 return;
483
484 case FencedStoreBarrier:
485 read(Heap);
486 write(JSCell_cellState);
487 return;
488
489 case CheckTraps:
490 read(InternalState);
491 write(InternalState);
492 return;
493
494 case InvalidationPoint:
495 write(SideState);
496 def(HeapLocation(InvalidationPointLoc, Watchpoint_fire), LazyNode(node));
497 return;
498
499 case Flush:
500 read(AbstractHeap(Stack, node->local()));
501 write(SideState);
502 return;
503
504 case NotifyWrite:
505 write(Watchpoint_fire);
506 write(SideState);
507 return;
508
509 case PushWithScope: {
510 read(World);
511 write(HeapObjectCount);
512 return;
513 }
514
515 case CreateActivation: {
516 SymbolTable* table = node->castOperand<SymbolTable*>();
517 if (table->singleton().isStillValid())
518 write(Watchpoint_fire);
519 read(HeapObjectCount);
520 write(HeapObjectCount);
521 return;
522 }
523
524 case CreateDirectArguments:
525 case CreateScopedArguments:
526 case CreateClonedArguments:
527 read(Stack);
528 read(HeapObjectCount);
529 write(HeapObjectCount);
530 return;
531
532 case PhantomDirectArguments:
533 case PhantomClonedArguments:
534 // DFG backend requires that the locals that this reads are flushed. FTL backend can handle those
535 // locals being promoted.
536 if (!graph.m_plan.isFTL())
537 read(Stack);
538
539 // Even though it's phantom, it still has the property that one can't be replaced with another.
540 read(HeapObjectCount);
541 write(HeapObjectCount);
542 return;
543
544 case PhantomSpread:
545 case PhantomNewArrayWithSpread:
546 case PhantomNewArrayBuffer:
547 case PhantomCreateRest:
548 // Even though it's phantom, it still has the property that one can't be replaced with another.
549 read(HeapObjectCount);
550 write(HeapObjectCount);
551 return;
552
553 case CallObjectConstructor:
554 read(HeapObjectCount);
555 write(HeapObjectCount);
556 return;
557
558 case ToThis:
559 read(MiscFields);
560 read(HeapObjectCount);
561 write(HeapObjectCount);
562 return;
563
564 case IsObjectOrNull:
565 read(MiscFields);
566 def(HeapLocation(IsObjectOrNullLoc, MiscFields, node->child1()), LazyNode(node));
567 return;
568
569 case IsFunction:
570 read(MiscFields);
571 def(HeapLocation(IsFunctionLoc, MiscFields, node->child1()), LazyNode(node));
572 return;
573
574 case MatchStructure:
575 read(JSCell_structureID);
576 return;
577
578 case ArraySlice:
579 read(MiscFields);
580 read(JSCell_indexingType);
581 read(JSCell_structureID);
582 read(JSObject_butterfly);
583 read(Butterfly_publicLength);
584 read(IndexedDoubleProperties);
585 read(IndexedInt32Properties);
586 read(IndexedContiguousProperties);
587 read(HeapObjectCount);
588 write(HeapObjectCount);
589 return;
590
591 case ArrayIndexOf: {
592 // FIXME: Should support a CSE rule.
593 // https://bugs.webkit.org/show_bug.cgi?id=173173
594 read(MiscFields);
595 read(JSCell_indexingType);
596 read(JSCell_structureID);
597 read(JSObject_butterfly);
598 read(Butterfly_publicLength);
599 switch (node->arrayMode().type()) {
600 case Array::Double:
601 read(IndexedDoubleProperties);
602 return;
603 case Array::Int32:
604 read(IndexedInt32Properties);
605 return;
606 case Array::Contiguous:
607 read(IndexedContiguousProperties);
608 return;
609 default:
610 RELEASE_ASSERT_NOT_REACHED();
611 return;
612 }
613 return;
614 }
615
616 case GetById:
617 case GetByIdFlush:
618 case GetByIdWithThis:
619 case GetByIdDirect:
620 case GetByIdDirectFlush:
621 case GetByValWithThis:
622 case PutById:
623 case PutByIdWithThis:
624 case PutByValWithThis:
625 case PutByIdFlush:
626 case PutByIdDirect:
627 case PutGetterById:
628 case PutSetterById:
629 case PutGetterSetterById:
630 case PutGetterByVal:
631 case PutSetterByVal:
632 case DefineDataProperty:
633 case DefineAccessorProperty:
634 case DeleteById:
635 case DeleteByVal:
636 case ArrayPush:
637 case ArrayPop:
638 case Call:
639 case DirectCall:
640 case TailCallInlinedCaller:
641 case DirectTailCallInlinedCaller:
642 case Construct:
643 case DirectConstruct:
644 case CallVarargs:
645 case CallForwardVarargs:
646 case TailCallVarargsInlinedCaller:
647 case TailCallForwardVarargsInlinedCaller:
648 case ConstructVarargs:
649 case ConstructForwardVarargs:
650 case ToPrimitive:
651 case InByVal:
652 case InById:
653 case HasOwnProperty:
654 case ValueNegate:
655 case SetFunctionName:
656 case GetDynamicVar:
657 case PutDynamicVar:
658 case ResolveScopeForHoistingFuncDeclInEval:
659 case ResolveScope:
660 case ToObject:
661 case HasGenericProperty:
662 case HasStructureProperty:
663 case GetPropertyEnumerator:
664 case GetDirectPname:
665 case InstanceOfCustom:
666 case ToNumber:
667 case NumberToStringWithRadix:
668 case CreateThis:
669 case InstanceOf:
670 case StringValueOf:
671 case ObjectKeys:
672 read(World);
673 write(Heap);
674 return;
675
676 case ValueBitAnd:
677 case ValueBitXor:
678 case ValueBitOr:
679 case ValueAdd:
680 case ValueSub:
681 case ValueMul:
682 case ValueDiv:
683 case ValueMod:
684 case ValuePow:
685 if (node->isBinaryUseKind(BigIntUse)) {
686 def(PureValue(node));
687 return;
688 }
689 read(World);
690 write(Heap);
691 return;
692
693 case AtomicsAdd:
694 case AtomicsAnd:
695 case AtomicsCompareExchange:
696 case AtomicsExchange:
697 case AtomicsLoad:
698 case AtomicsOr:
699 case AtomicsStore:
700 case AtomicsSub:
701 case AtomicsXor: {
702 unsigned numExtraArgs = numExtraAtomicsArgs(node->op());
703 Edge storageEdge = graph.child(node, 2 + numExtraArgs);
704 if (!storageEdge) {
705 read(World);
706 write(Heap);
707 return;
708 }
709 read(TypedArrayProperties);
710 read(MiscFields);
711 write(TypedArrayProperties);
712 return;
713 }
714
715 case CallEval:
716 ASSERT(!node->origin.semantic.inlineCallFrame());
717 read(AbstractHeap(Stack, graph.m_codeBlock->scopeRegister()));
718 read(AbstractHeap(Stack, virtualRegisterForArgument(0)));
719 read(World);
720 write(Heap);
721 return;
722
723 case Throw:
724 case ThrowStaticError:
725 case TailCall:
726 case DirectTailCall:
727 case TailCallVarargs:
728 case TailCallForwardVarargs:
729 read(World);
730 write(SideState);
731 return;
732
733 case GetGetter:
734 read(GetterSetter_getter);
735 def(HeapLocation(GetterLoc, GetterSetter_getter, node->child1()), LazyNode(node));
736 return;
737
738 case GetSetter:
739 read(GetterSetter_setter);
740 def(HeapLocation(SetterLoc, GetterSetter_setter, node->child1()), LazyNode(node));
741 return;
742
743 case GetCallee:
744 read(AbstractHeap(Stack, CallFrameSlot::callee));
745 def(HeapLocation(StackLoc, AbstractHeap(Stack, CallFrameSlot::callee)), LazyNode(node));
746 return;
747
748 case SetCallee:
749 write(AbstractHeap(Stack, CallFrameSlot::callee));
750 return;
751
752 case GetArgumentCountIncludingThis: {
753 auto heap = AbstractHeap(Stack, remapOperand(node->argumentsInlineCallFrame(), VirtualRegister(CallFrameSlot::argumentCount)));
754 read(heap);
755 def(HeapLocation(StackPayloadLoc, heap), LazyNode(node));
756 return;
757 }
758
759 case SetArgumentCountIncludingThis:
760 write(AbstractHeap(Stack, CallFrameSlot::argumentCount));
761 return;
762
763 case GetRestLength:
764 read(Stack);
765 return;
766
767 case GetLocal:
768 read(AbstractHeap(Stack, node->local()));
769 def(HeapLocation(StackLoc, AbstractHeap(Stack, node->local())), LazyNode(node));
770 return;
771
772 case SetLocal:
773 write(AbstractHeap(Stack, node->local()));
774 def(HeapLocation(StackLoc, AbstractHeap(Stack, node->local())), LazyNode(node->child1().node()));
775 return;
776
777 case GetStack: {
778 AbstractHeap heap(Stack, node->stackAccessData()->local);
779 read(heap);
780 def(HeapLocation(StackLoc, heap), LazyNode(node));
781 return;
782 }
783
784 case PutStack: {
785 AbstractHeap heap(Stack, node->stackAccessData()->local);
786 write(heap);
787 def(HeapLocation(StackLoc, heap), LazyNode(node->child1().node()));
788 return;
789 }
790
791 case LoadVarargs: {
792 read(World);
793 write(Heap);
794 LoadVarargsData* data = node->loadVarargsData();
795 write(AbstractHeap(Stack, data->count.offset()));
796 for (unsigned i = data->limit; i--;)
797 write(AbstractHeap(Stack, data->start.offset() + static_cast<int>(i)));
798 return;
799 }
800
801 case ForwardVarargs: {
802 // We could be way more precise here.
803 read(Stack);
804
805 LoadVarargsData* data = node->loadVarargsData();
806 write(AbstractHeap(Stack, data->count.offset()));
807 for (unsigned i = data->limit; i--;)
808 write(AbstractHeap(Stack, data->start.offset() + static_cast<int>(i)));
809 return;
810 }
811
812 case GetByVal: {
813 ArrayMode mode = node->arrayMode();
814 LocationKind indexedPropertyLoc = indexedPropertyLocForResultType(node->result());
815 switch (mode.type()) {
816 case Array::SelectUsingPredictions:
817 case Array::Unprofiled:
818 case Array::SelectUsingArguments:
819 // Assume the worst since we don't have profiling yet.
820 read(World);
821 write(Heap);
822 return;
823
824 case Array::ForceExit:
825 write(SideState);
826 return;
827
828 case Array::Generic:
829 read(World);
830 write(Heap);
831 return;
832
833 case Array::String:
834 if (mode.isOutOfBounds()) {
835 read(World);
836 write(Heap);
837 return;
838 }
839 // This appears to read nothing because it's only reading immutable data.
840 def(PureValue(graph, node, mode.asWord()));
841 return;
842
843 case Array::DirectArguments:
844 if (mode.isInBounds()) {
845 read(DirectArgumentsProperties);
846 def(HeapLocation(indexedPropertyLoc, DirectArgumentsProperties, graph.varArgChild(node, 0), graph.varArgChild(node, 1)), LazyNode(node));
847 return;
848 }
849 read(World);
850 write(Heap);
851 return;
852
853 case Array::ScopedArguments:
854 read(ScopeProperties);
855 def(HeapLocation(indexedPropertyLoc, ScopeProperties, graph.varArgChild(node, 0), graph.varArgChild(node, 1)), LazyNode(node));
856 return;
857
858 case Array::Int32:
859 if (mode.isInBounds()) {
860 read(Butterfly_publicLength);
861 read(IndexedInt32Properties);
862 def(HeapLocation(indexedPropertyLoc, IndexedInt32Properties, graph.varArgChild(node, 0), graph.varArgChild(node, 1)), LazyNode(node));
863 return;
864 }
865 read(World);
866 write(Heap);
867 return;
868
869 case Array::Double:
870 if (mode.isInBounds()) {
871 read(Butterfly_publicLength);
872 read(IndexedDoubleProperties);
873 LocationKind kind = mode.isSaneChain() ? IndexedPropertyDoubleSaneChainLoc : IndexedPropertyDoubleLoc;
874 def(HeapLocation(kind, IndexedDoubleProperties, graph.varArgChild(node, 0), graph.varArgChild(node, 1)), LazyNode(node));
875 return;
876 }
877 read(World);
878 write(Heap);
879 return;
880
881 case Array::Contiguous:
882 if (mode.isInBounds()) {
883 read(Butterfly_publicLength);
884 read(IndexedContiguousProperties);
885 def(HeapLocation(indexedPropertyLoc, IndexedContiguousProperties, graph.varArgChild(node, 0), graph.varArgChild(node, 1)), LazyNode(node));
886 return;
887 }
888 read(World);
889 write(Heap);
890 return;
891
892 case Array::Undecided:
893 def(PureValue(graph, node));
894 return;
895
896 case Array::ArrayStorage:
897 case Array::SlowPutArrayStorage:
898 if (mode.isInBounds()) {
899 read(Butterfly_vectorLength);
900 read(IndexedArrayStorageProperties);
901 return;
902 }
903 read(World);
904 write(Heap);
905 return;
906
907 case Array::Int8Array:
908 case Array::Int16Array:
909 case Array::Int32Array:
910 case Array::Uint8Array:
911 case Array::Uint8ClampedArray:
912 case Array::Uint16Array:
913 case Array::Uint32Array:
914 case Array::Float32Array:
915 case Array::Float64Array:
916 read(TypedArrayProperties);
917 read(MiscFields);
918 def(HeapLocation(indexedPropertyLoc, TypedArrayProperties, graph.varArgChild(node, 0), graph.varArgChild(node, 1)), LazyNode(node));
919 return;
920 // We should not get an AnyTypedArray in a GetByVal as AnyTypedArray is only created from intrinsics, which
921 // are only added from Inline Caching a GetById.
922 case Array::AnyTypedArray:
923 DFG_CRASH(graph, node, "impossible array mode for get");
924 return;
925 }
926 RELEASE_ASSERT_NOT_REACHED();
927 return;
928 }
929
930 case GetMyArgumentByVal:
931 case GetMyArgumentByValOutOfBounds: {
932 read(Stack);
933 // FIXME: It would be trivial to have a def here.
934 // https://bugs.webkit.org/show_bug.cgi?id=143077
935 return;
936 }
937
938 case PutByValDirect:
939 case PutByVal:
940 case PutByValAlias: {
941 ArrayMode mode = node->arrayMode();
942 Node* base = graph.varArgChild(node, 0).node();
943 Node* index = graph.varArgChild(node, 1).node();
944 Node* value = graph.varArgChild(node, 2).node();
945 LocationKind indexedPropertyLoc = indexedPropertyLocForResultType(node->result());
946
947 switch (mode.modeForPut().type()) {
948 case Array::SelectUsingPredictions:
949 case Array::SelectUsingArguments:
950 case Array::Unprofiled:
951 case Array::Undecided:
952 // Assume the worst since we don't have profiling yet.
953 read(World);
954 write(Heap);
955 return;
956
957 case Array::ForceExit:
958 write(SideState);
959 return;
960
961 case Array::Generic:
962 read(World);
963 write(Heap);
964 return;
965
966 case Array::Int32:
967 if (node->arrayMode().isOutOfBounds()) {
968 read(World);
969 write(Heap);
970 return;
971 }
972 read(Butterfly_publicLength);
973 read(Butterfly_vectorLength);
974 read(IndexedInt32Properties);
975 write(IndexedInt32Properties);
976 if (node->arrayMode().mayStoreToHole())
977 write(Butterfly_publicLength);
978 def(HeapLocation(indexedPropertyLoc, IndexedInt32Properties, base, index), LazyNode(value));
979 return;
980
981 case Array::Double:
982 if (node->arrayMode().isOutOfBounds()) {
983 read(World);
984 write(Heap);
985 return;
986 }
987 read(Butterfly_publicLength);
988 read(Butterfly_vectorLength);
989 read(IndexedDoubleProperties);
990 write(IndexedDoubleProperties);
991 if (node->arrayMode().mayStoreToHole())
992 write(Butterfly_publicLength);
993 def(HeapLocation(IndexedPropertyDoubleLoc, IndexedDoubleProperties, base, index), LazyNode(value));
994 def(HeapLocation(IndexedPropertyDoubleSaneChainLoc, IndexedDoubleProperties, base, index), LazyNode(value));
995 return;
996
997 case Array::Contiguous:
998 if (node->arrayMode().isOutOfBounds()) {
999 read(World);
1000 write(Heap);
1001 return;
1002 }
1003 read(Butterfly_publicLength);
1004 read(Butterfly_vectorLength);
1005 read(IndexedContiguousProperties);
1006 write(IndexedContiguousProperties);
1007 if (node->arrayMode().mayStoreToHole())
1008 write(Butterfly_publicLength);
1009 def(HeapLocation(indexedPropertyLoc, IndexedContiguousProperties, base, index), LazyNode(value));
1010 return;
1011
1012 case Array::ArrayStorage:
1013 if (node->arrayMode().isOutOfBounds()) {
1014 read(World);
1015 write(Heap);
1016 return;
1017 }
1018 read(Butterfly_publicLength);
1019 read(Butterfly_vectorLength);
1020 read(ArrayStorageProperties);
1021 write(ArrayStorageProperties);
1022 if (node->arrayMode().mayStoreToHole())
1023 write(Butterfly_publicLength);
1024 return;
1025
1026 case Array::SlowPutArrayStorage:
1027 if (node->arrayMode().mayStoreToHole()) {
1028 read(World);
1029 write(Heap);
1030 return;
1031 }
1032 read(Butterfly_publicLength);
1033 read(Butterfly_vectorLength);
1034 read(ArrayStorageProperties);
1035 write(ArrayStorageProperties);
1036 return;
1037
1038 case Array::Int8Array:
1039 case Array::Int16Array:
1040 case Array::Int32Array:
1041 case Array::Uint8Array:
1042 case Array::Uint8ClampedArray:
1043 case Array::Uint16Array:
1044 case Array::Uint32Array:
1045 case Array::Float32Array:
1046 case Array::Float64Array:
1047 read(MiscFields);
1048 write(TypedArrayProperties);
1049 // FIXME: We can't def() anything here because these operations truncate their inputs.
1050 // https://bugs.webkit.org/show_bug.cgi?id=134737
1051 return;
1052 case Array::AnyTypedArray:
1053 case Array::String:
1054 case Array::DirectArguments:
1055 case Array::ScopedArguments:
1056 DFG_CRASH(graph, node, "impossible array mode for put");
1057 return;
1058 }
1059 RELEASE_ASSERT_NOT_REACHED();
1060 return;
1061 }
1062
1063 case CheckStructureOrEmpty:
1064 case CheckStructure:
1065 read(JSCell_structureID);
1066 return;
1067
1068 case CheckArray:
1069 read(JSCell_indexingType);
1070 read(JSCell_typeInfoType);
1071 read(JSCell_structureID);
1072 return;
1073
1074 case CheckTypeInfoFlags:
1075 read(JSCell_typeInfoFlags);
1076 def(HeapLocation(CheckTypeInfoFlagsLoc, JSCell_typeInfoFlags, node->child1()), LazyNode(node));
1077 return;
1078
1079 case ParseInt:
1080 // Note: We would have eliminated a ParseInt that has just a single child as an Int32Use inside fixup.
1081 if (node->child1().useKind() == StringUse && (!node->child2() || node->child2().useKind() == Int32Use)) {
1082 def(PureValue(node));
1083 return;
1084 }
1085
1086 read(World);
1087 write(Heap);
1088 return;
1089
1090 case OverridesHasInstance:
1091 read(JSCell_typeInfoFlags);
1092 def(HeapLocation(OverridesHasInstanceLoc, JSCell_typeInfoFlags, node->child1()), LazyNode(node));
1093 return;
1094
1095 case PutStructure:
1096 read(JSObject_butterfly);
1097 write(JSCell_structureID);
1098 write(JSCell_typeInfoType);
1099 write(JSCell_typeInfoFlags);
1100 write(JSCell_indexingType);
1101 return;
1102
1103 case AllocatePropertyStorage:
1104 case ReallocatePropertyStorage:
1105 read(HeapObjectCount);
1106 write(HeapObjectCount);
1107 return;
1108
1109 case NukeStructureAndSetButterfly:
1110 write(JSObject_butterfly);
1111 write(JSCell_structureID);
1112 def(HeapLocation(ButterflyLoc, JSObject_butterfly, node->child1()), LazyNode(node->child2().node()));
1113 return;
1114
1115 case GetButterfly:
1116 read(JSObject_butterfly);
1117 def(HeapLocation(ButterflyLoc, JSObject_butterfly, node->child1()), LazyNode(node));
1118 return;
1119
1120 case CheckSubClass:
1121 def(PureValue(node, node->classInfo()));
1122 return;
1123
1124 case CallDOMGetter: {
1125 DOMJIT::CallDOMGetterSnippet* snippet = node->callDOMGetterData()->snippet;
1126 if (!snippet) {
1127 read(World);
1128 write(Heap);
1129 return;
1130 }
1131 DOMJIT::Effect effect = snippet->effect;
1132 if (effect.reads) {
1133 if (effect.reads == DOMJIT::HeapRange::top())
1134 read(World);
1135 else
1136 read(AbstractHeap(DOMState, effect.reads.rawRepresentation()));
1137 }
1138 if (effect.writes) {
1139 if (effect.writes == DOMJIT::HeapRange::top())
1140 write(Heap);
1141 else
1142 write(AbstractHeap(DOMState, effect.writes.rawRepresentation()));
1143 }
1144 if (effect.def != DOMJIT::HeapRange::top()) {
1145 DOMJIT::HeapRange range = effect.def;
1146 if (range == DOMJIT::HeapRange::none())
1147 def(PureValue(node, bitwise_cast<uintptr_t>(node->callDOMGetterData()->customAccessorGetter)));
1148 else {
1149 // Def with heap location. We do not include "GlobalObject" for that since this information is included in the base node.
1150 // We only see the DOMJIT getter here. So just including "base" is ok.
1151 def(HeapLocation(DOMStateLoc, AbstractHeap(DOMState, range.rawRepresentation()), node->child1()), LazyNode(node));
1152 }
1153 }
1154 return;
1155 }
1156
1157 case CallDOM: {
1158 const DOMJIT::Signature* signature = node->signature();
1159 DOMJIT::Effect effect = signature->effect;
1160 if (effect.reads) {
1161 if (effect.reads == DOMJIT::HeapRange::top())
1162 read(World);
1163 else
1164 read(AbstractHeap(DOMState, effect.reads.rawRepresentation()));
1165 }
1166 if (effect.writes) {
1167 if (effect.writes == DOMJIT::HeapRange::top())
1168 write(Heap);
1169 else
1170 write(AbstractHeap(DOMState, effect.writes.rawRepresentation()));
1171 }
1172 ASSERT_WITH_MESSAGE(effect.def == DOMJIT::HeapRange::top(), "Currently, we do not accept any def for CallDOM.");
1173 return;
1174 }
1175
1176 case Arrayify:
1177 case ArrayifyToStructure:
1178 read(JSCell_structureID);
1179 read(JSCell_indexingType);
1180 read(JSObject_butterfly);
1181 write(JSCell_structureID);
1182 write(JSCell_indexingType);
1183 write(JSObject_butterfly);
1184 write(Watchpoint_fire);
1185 return;
1186
1187 case GetIndexedPropertyStorage:
1188 if (node->arrayMode().type() == Array::String) {
1189 def(PureValue(node, node->arrayMode().asWord()));
1190 return;
1191 }
1192 read(MiscFields);
1193 def(HeapLocation(IndexedPropertyStorageLoc, MiscFields, node->child1()), LazyNode(node));
1194 return;
1195
1196 case GetTypedArrayByteOffset:
1197 read(MiscFields);
1198 def(HeapLocation(TypedArrayByteOffsetLoc, MiscFields, node->child1()), LazyNode(node));
1199 return;
1200
1201 case GetPrototypeOf: {
1202 switch (node->child1().useKind()) {
1203 case ArrayUse:
1204 case FunctionUse:
1205 case FinalObjectUse:
1206 read(JSCell_structureID);
1207 read(JSObject_butterfly);
1208 read(NamedProperties); // Poly proto could load prototype from its slot.
1209 def(HeapLocation(PrototypeLoc, NamedProperties, node->child1()), LazyNode(node));
1210 return;
1211 default:
1212 read(World);
1213 write(Heap);
1214 return;
1215 }
1216 }
1217
1218 case GetByOffset:
1219 case GetGetterSetterByOffset: {
1220 unsigned identifierNumber = node->storageAccessData().identifierNumber;
1221 AbstractHeap heap(NamedProperties, identifierNumber);
1222 read(heap);
1223 def(HeapLocation(NamedPropertyLoc, heap, node->child2()), LazyNode(node));
1224 return;
1225 }
1226
1227 case TryGetById: {
1228 read(Heap);
1229 return;
1230 }
1231
1232 case MultiGetByOffset: {
1233 read(JSCell_structureID);
1234 read(JSObject_butterfly);
1235 AbstractHeap heap(NamedProperties, node->multiGetByOffsetData().identifierNumber);
1236 read(heap);
1237 def(HeapLocation(NamedPropertyLoc, heap, node->child1()), LazyNode(node));
1238 return;
1239 }
1240
1241 case MultiPutByOffset: {
1242 read(JSCell_structureID);
1243 read(JSObject_butterfly);
1244 AbstractHeap heap(NamedProperties, node->multiPutByOffsetData().identifierNumber);
1245 write(heap);
1246 if (node->multiPutByOffsetData().writesStructures())
1247 write(JSCell_structureID);
1248 if (node->multiPutByOffsetData().reallocatesStorage())
1249 write(JSObject_butterfly);
1250 def(HeapLocation(NamedPropertyLoc, heap, node->child1()), LazyNode(node->child2().node()));
1251 return;
1252 }
1253
1254 case PutByOffset: {
1255 unsigned identifierNumber = node->storageAccessData().identifierNumber;
1256 AbstractHeap heap(NamedProperties, identifierNumber);
1257 write(heap);
1258 def(HeapLocation(NamedPropertyLoc, heap, node->child2()), LazyNode(node->child3().node()));
1259 return;
1260 }
1261
1262 case GetArrayLength: {
1263 ArrayMode mode = node->arrayMode();
1264 switch (mode.type()) {
1265 case Array::Undecided:
1266 case Array::Int32:
1267 case Array::Double:
1268 case Array::Contiguous:
1269 case Array::ArrayStorage:
1270 case Array::SlowPutArrayStorage:
1271 read(Butterfly_publicLength);
1272 def(HeapLocation(ArrayLengthLoc, Butterfly_publicLength, node->child1()), LazyNode(node));
1273 return;
1274
1275 case Array::String:
1276 def(PureValue(node, mode.asWord()));
1277 return;
1278
1279 case Array::DirectArguments:
1280 case Array::ScopedArguments:
1281 read(MiscFields);
1282 def(HeapLocation(ArrayLengthLoc, MiscFields, node->child1()), LazyNode(node));
1283 return;
1284
1285 default:
1286 ASSERT(mode.isSomeTypedArrayView());
1287 read(MiscFields);
1288 def(HeapLocation(ArrayLengthLoc, MiscFields, node->child1()), LazyNode(node));
1289 return;
1290 }
1291 }
1292
1293 case GetVectorLength: {
1294 ArrayMode mode = node->arrayMode();
1295 switch (mode.type()) {
1296 case Array::ArrayStorage:
1297 case Array::SlowPutArrayStorage:
1298 read(Butterfly_vectorLength);
1299 def(HeapLocation(VectorLengthLoc, Butterfly_vectorLength, node->child1()), LazyNode(node));
1300 return;
1301
1302 default:
1303 RELEASE_ASSERT_NOT_REACHED();
1304 return;
1305 }
1306 }
1307
1308 case GetClosureVar:
1309 read(AbstractHeap(ScopeProperties, node->scopeOffset().offset()));
1310 def(HeapLocation(ClosureVariableLoc, AbstractHeap(ScopeProperties, node->scopeOffset().offset()), node->child1()), LazyNode(node));
1311 return;
1312
1313 case PutClosureVar:
1314 write(AbstractHeap(ScopeProperties, node->scopeOffset().offset()));
1315 def(HeapLocation(ClosureVariableLoc, AbstractHeap(ScopeProperties, node->scopeOffset().offset()), node->child1()), LazyNode(node->child2().node()));
1316 return;
1317
1318 case GetRegExpObjectLastIndex:
1319 read(RegExpObject_lastIndex);
1320 def(HeapLocation(RegExpObjectLastIndexLoc, RegExpObject_lastIndex, node->child1()), LazyNode(node));
1321 return;
1322
1323 case SetRegExpObjectLastIndex:
1324 write(RegExpObject_lastIndex);
1325 def(HeapLocation(RegExpObjectLastIndexLoc, RegExpObject_lastIndex, node->child1()), LazyNode(node->child2().node()));
1326 return;
1327
1328 case RecordRegExpCachedResult:
1329 write(RegExpState);
1330 return;
1331
1332 case GetFromArguments: {
1333 AbstractHeap heap(DirectArgumentsProperties, node->capturedArgumentsOffset().offset());
1334 read(heap);
1335 def(HeapLocation(DirectArgumentsLoc, heap, node->child1()), LazyNode(node));
1336 return;
1337 }
1338
1339 case PutToArguments: {
1340 AbstractHeap heap(DirectArgumentsProperties, node->capturedArgumentsOffset().offset());
1341 write(heap);
1342 def(HeapLocation(DirectArgumentsLoc, heap, node->child1()), LazyNode(node->child2().node()));
1343 return;
1344 }
1345
1346 case GetArgument: {
1347 read(Stack);
1348 // FIXME: It would be trivial to have a def here.
1349 // https://bugs.webkit.org/show_bug.cgi?id=143077
1350 return;
1351 }
1352
1353 case GetGlobalVar:
1354 case GetGlobalLexicalVariable:
1355 read(AbstractHeap(Absolute, node->variablePointer()));
1356 def(HeapLocation(GlobalVariableLoc, AbstractHeap(Absolute, node->variablePointer())), LazyNode(node));
1357 return;
1358
1359 case PutGlobalVariable:
1360 write(AbstractHeap(Absolute, node->variablePointer()));
1361 def(HeapLocation(GlobalVariableLoc, AbstractHeap(Absolute, node->variablePointer())), LazyNode(node->child2().node()));
1362 return;
1363
1364 case NewArrayWithSize:
1365 read(HeapObjectCount);
1366 write(HeapObjectCount);
1367 return;
1368
1369 case NewTypedArray:
1370 switch (node->child1().useKind()) {
1371 case Int32Use:
1372 read(HeapObjectCount);
1373 write(HeapObjectCount);
1374 return;
1375 case UntypedUse:
1376 read(World);
1377 write(Heap);
1378 return;
1379 default:
1380 DFG_CRASH(graph, node, "Bad use kind");
1381 }
1382 break;
1383
1384 case NewArrayWithSpread: {
1385 // This also reads from JSFixedArray's data store, but we don't have any way of describing that yet.
1386 read(HeapObjectCount);
1387 for (unsigned i = 0; i < node->numChildren(); i++) {
1388 Node* child = graph.varArgChild(node, i).node();
1389 if (child->op() == PhantomSpread) {
1390 read(Stack);
1391 break;
1392 }
1393 }
1394 write(HeapObjectCount);
1395 return;
1396 }
1397
1398 case Spread: {
1399 if (node->child1()->op() == PhantomNewArrayBuffer) {
1400 read(MiscFields);
1401 return;
1402 }
1403
1404 if (node->child1()->op() == PhantomCreateRest) {
1405 read(Stack);
1406 write(HeapObjectCount);
1407 return;
1408 }
1409
1410 read(World);
1411 write(Heap);
1412 return;
1413 }
1414
1415 case NewArray: {
1416 read(HeapObjectCount);
1417 write(HeapObjectCount);
1418
1419 unsigned numElements = node->numChildren();
1420
1421 def(HeapLocation(ArrayLengthLoc, Butterfly_publicLength, node),
1422 LazyNode(graph.freeze(jsNumber(numElements))));
1423
1424 if (!numElements)
1425 return;
1426
1427 AbstractHeap heap;
1428 LocationKind indexedPropertyLoc;
1429 switch (node->indexingType()) {
1430 case ALL_DOUBLE_INDEXING_TYPES:
1431 heap = IndexedDoubleProperties;
1432 indexedPropertyLoc = IndexedPropertyDoubleLoc;
1433 break;
1434
1435 case ALL_INT32_INDEXING_TYPES:
1436 heap = IndexedInt32Properties;
1437 indexedPropertyLoc = IndexedPropertyJSLoc;
1438 break;
1439
1440 case ALL_CONTIGUOUS_INDEXING_TYPES:
1441 heap = IndexedContiguousProperties;
1442 indexedPropertyLoc = IndexedPropertyJSLoc;
1443 break;
1444
1445 default:
1446 return;
1447 }
1448
1449 if (numElements < graph.m_uint32ValuesInUse.size()) {
1450 for (unsigned operandIdx = 0; operandIdx < numElements; ++operandIdx) {
1451 Edge use = graph.m_varArgChildren[node->firstChild() + operandIdx];
1452 def(HeapLocation(indexedPropertyLoc, heap, node, LazyNode(graph.freeze(jsNumber(operandIdx)))),
1453 LazyNode(use.node()));
1454 }
1455 } else {
1456 for (uint32_t operandIdx : graph.m_uint32ValuesInUse) {
1457 if (operandIdx >= numElements)
1458 continue;
1459 Edge use = graph.m_varArgChildren[node->firstChild() + operandIdx];
1460 // operandIdx comes from graph.m_uint32ValuesInUse and thus is guaranteed to be already frozen
1461 def(HeapLocation(indexedPropertyLoc, heap, node, LazyNode(graph.freeze(jsNumber(operandIdx)))),
1462 LazyNode(use.node()));
1463 }
1464 }
1465 return;
1466 }
1467
1468 case NewArrayBuffer: {
1469 read(HeapObjectCount);
1470 write(HeapObjectCount);
1471
1472 auto* array = node->castOperand<JSImmutableButterfly*>();
1473 unsigned numElements = array->length();
1474 def(HeapLocation(ArrayLengthLoc, Butterfly_publicLength, node),
1475 LazyNode(graph.freeze(jsNumber(numElements))));
1476
1477 AbstractHeap heap;
1478 LocationKind indexedPropertyLoc;
1479 NodeType op = JSConstant;
1480 switch (node->indexingType()) {
1481 case ALL_DOUBLE_INDEXING_TYPES:
1482 heap = IndexedDoubleProperties;
1483 indexedPropertyLoc = IndexedPropertyDoubleLoc;
1484 op = DoubleConstant;
1485 break;
1486
1487 case ALL_INT32_INDEXING_TYPES:
1488 heap = IndexedInt32Properties;
1489 indexedPropertyLoc = IndexedPropertyJSLoc;
1490 break;
1491
1492 case ALL_CONTIGUOUS_INDEXING_TYPES:
1493 heap = IndexedContiguousProperties;
1494 indexedPropertyLoc = IndexedPropertyJSLoc;
1495 break;
1496
1497 default:
1498 return;
1499 }
1500
1501 if (numElements < graph.m_uint32ValuesInUse.size()) {
1502 for (unsigned index = 0; index < numElements; ++index) {
1503 def(HeapLocation(indexedPropertyLoc, heap, node, LazyNode(graph.freeze(jsNumber(index)))),
1504 LazyNode(graph.freeze(array->get(index)), op));
1505 }
1506 } else {
1507 Vector<uint32_t> possibleIndices;
1508 for (uint32_t index : graph.m_uint32ValuesInUse) {
1509 if (index >= numElements)
1510 continue;
1511 possibleIndices.append(index);
1512 }
1513 for (uint32_t index : possibleIndices) {
1514 def(HeapLocation(indexedPropertyLoc, heap, node, LazyNode(graph.freeze(jsNumber(index)))),
1515 LazyNode(graph.freeze(array->get(index)), op));
1516 }
1517 }
1518 return;
1519 }
1520
1521 case CreateRest: {
1522 if (!graph.isWatchingHavingABadTimeWatchpoint(node)) {
1523 // This means we're already having a bad time.
1524 read(World);
1525 write(Heap);
1526 return;
1527 }
1528 read(Stack);
1529 read(HeapObjectCount);
1530 write(HeapObjectCount);
1531 return;
1532 }
1533
1534 case ObjectCreate: {
1535 switch (node->child1().useKind()) {
1536 case ObjectUse:
1537 read(HeapObjectCount);
1538 write(HeapObjectCount);
1539 return;
1540 case UntypedUse:
1541 read(World);
1542 write(Heap);
1543 return;
1544 default:
1545 RELEASE_ASSERT_NOT_REACHED();
1546 return;
1547 }
1548 }
1549
1550 case NewObject:
1551 case NewRegexp:
1552 case NewSymbol:
1553 case NewStringObject:
1554 case PhantomNewObject:
1555 case MaterializeNewObject:
1556 case PhantomNewFunction:
1557 case PhantomNewGeneratorFunction:
1558 case PhantomNewAsyncFunction:
1559 case PhantomNewAsyncGeneratorFunction:
1560 case PhantomCreateActivation:
1561 case MaterializeCreateActivation:
1562 case PhantomNewRegexp:
1563 read(HeapObjectCount);
1564 write(HeapObjectCount);
1565 return;
1566
1567 case NewFunction:
1568 case NewGeneratorFunction:
1569 case NewAsyncGeneratorFunction:
1570 case NewAsyncFunction:
1571 if (node->castOperand<FunctionExecutable*>()->singleton().isStillValid())
1572 write(Watchpoint_fire);
1573 read(HeapObjectCount);
1574 write(HeapObjectCount);
1575 return;
1576
1577 case RegExpExec:
1578 case RegExpTest:
1579 // Even if we've proven known input types as RegExpObject and String,
1580 // accessing lastIndex is effectful if it's a global regexp.
1581 read(World);
1582 write(Heap);
1583 return;
1584
1585 case RegExpMatchFast:
1586 read(RegExpState);
1587 read(RegExpObject_lastIndex);
1588 write(RegExpState);
1589 write(RegExpObject_lastIndex);
1590 return;
1591
1592 case RegExpExecNonGlobalOrSticky:
1593 case RegExpMatchFastGlobal:
1594 read(RegExpState);
1595 write(RegExpState);
1596 return;
1597
1598 case StringReplace:
1599 case StringReplaceRegExp:
1600 if (node->child1().useKind() == StringUse
1601 && node->child2().useKind() == RegExpObjectUse
1602 && node->child3().useKind() == StringUse) {
1603 read(RegExpState);
1604 read(RegExpObject_lastIndex);
1605 write(RegExpState);
1606 write(RegExpObject_lastIndex);
1607 return;
1608 }
1609 read(World);
1610 write(Heap);
1611 return;
1612
1613 case StringCharAt:
1614 if (node->arrayMode().isOutOfBounds()) {
1615 read(World);
1616 write(Heap);
1617 return;
1618 }
1619 def(PureValue(node));
1620 return;
1621
1622 case CompareBelow:
1623 case CompareBelowEq:
1624 def(PureValue(node));
1625 return;
1626
1627 case CompareEq:
1628 case CompareLess:
1629 case CompareLessEq:
1630 case CompareGreater:
1631 case CompareGreaterEq:
1632 if (node->isBinaryUseKind(StringUse)) {
1633 read(HeapObjectCount);
1634 write(HeapObjectCount);
1635 return;
1636 }
1637
1638 if (node->isBinaryUseKind(UntypedUse)) {
1639 read(World);
1640 write(Heap);
1641 return;
1642 }
1643
1644 def(PureValue(node));
1645 return;
1646
1647 case ToString:
1648 case CallStringConstructor:
1649 switch (node->child1().useKind()) {
1650 case CellUse:
1651 case UntypedUse:
1652 read(World);
1653 write(Heap);
1654 return;
1655
1656 case StringObjectUse:
1657 case StringOrStringObjectUse:
1658 // These two StringObjectUse's are pure because if we emit this node with either
1659 // of these UseKinds, we'll first emit a StructureCheck ensuring that we're the
1660 // original String or StringObject structure. Therefore, we don't have an overridden
1661 // valueOf, etc.
1662
1663 case Int32Use:
1664 case Int52RepUse:
1665 case DoubleRepUse:
1666 case NotCellUse:
1667 def(PureValue(node));
1668 return;
1669
1670 default:
1671 RELEASE_ASSERT_NOT_REACHED();
1672 return;
1673 }
1674
1675 case CountExecution:
1676 case SuperSamplerBegin:
1677 case SuperSamplerEnd:
1678 read(InternalState);
1679 write(InternalState);
1680 return;
1681
1682 case LogShadowChickenPrologue:
1683 case LogShadowChickenTail:
1684 write(SideState);
1685 return;
1686
1687 case MapHash:
1688 def(PureValue(node));
1689 return;
1690
1691 case NormalizeMapKey:
1692 def(PureValue(node));
1693 return;
1694
1695 case GetMapBucket: {
1696 Edge& mapEdge = node->child1();
1697 Edge& keyEdge = node->child2();
1698 AbstractHeapKind heap = (mapEdge.useKind() == MapObjectUse) ? JSMapFields : JSSetFields;
1699 read(heap);
1700 def(HeapLocation(MapBucketLoc, heap, mapEdge, keyEdge), LazyNode(node));
1701 return;
1702 }
1703
1704 case GetMapBucketHead: {
1705 Edge& mapEdge = node->child1();
1706 AbstractHeapKind heap = (mapEdge.useKind() == MapObjectUse) ? JSMapFields : JSSetFields;
1707 read(heap);
1708 def(HeapLocation(MapBucketHeadLoc, heap, mapEdge), LazyNode(node));
1709 return;
1710 }
1711
1712 case GetMapBucketNext: {
1713 AbstractHeapKind heap = (node->bucketOwnerType() == BucketOwnerType::Map) ? JSMapFields : JSSetFields;
1714 read(heap);
1715 Edge& bucketEdge = node->child1();
1716 def(HeapLocation(MapBucketNextLoc, heap, bucketEdge), LazyNode(node));
1717 return;
1718 }
1719
1720 case LoadKeyFromMapBucket: {
1721 AbstractHeapKind heap = (node->bucketOwnerType() == BucketOwnerType::Map) ? JSMapFields : JSSetFields;
1722 read(heap);
1723 Edge& bucketEdge = node->child1();
1724 def(HeapLocation(MapBucketKeyLoc, heap, bucketEdge), LazyNode(node));
1725 return;
1726 }
1727
1728 case LoadValueFromMapBucket: {
1729 AbstractHeapKind heap = (node->bucketOwnerType() == BucketOwnerType::Map) ? JSMapFields : JSSetFields;
1730 read(heap);
1731 Edge& bucketEdge = node->child1();
1732 def(HeapLocation(MapBucketValueLoc, heap, bucketEdge), LazyNode(node));
1733 return;
1734 }
1735
1736 case WeakMapGet: {
1737 Edge& mapEdge = node->child1();
1738 Edge& keyEdge = node->child2();
1739 AbstractHeapKind heap = (mapEdge.useKind() == WeakMapObjectUse) ? JSWeakMapFields : JSWeakSetFields;
1740 read(heap);
1741 def(HeapLocation(WeakMapGetLoc, heap, mapEdge, keyEdge), LazyNode(node));
1742 return;
1743 }
1744
1745 case SetAdd: {
1746 Edge& mapEdge = node->child1();
1747 Edge& keyEdge = node->child2();
1748 write(JSSetFields);
1749 def(HeapLocation(MapBucketLoc, JSSetFields, mapEdge, keyEdge), LazyNode(node));
1750 return;
1751 }
1752
1753 case MapSet: {
1754 Edge& mapEdge = graph.varArgChild(node, 0);
1755 Edge& keyEdge = graph.varArgChild(node, 1);
1756 write(JSMapFields);
1757 def(HeapLocation(MapBucketLoc, JSMapFields, mapEdge, keyEdge), LazyNode(node));
1758 return;
1759 }
1760
1761 case WeakSetAdd: {
1762 Edge& mapEdge = node->child1();
1763 Edge& keyEdge = node->child2();
1764 write(JSWeakSetFields);
1765 def(HeapLocation(WeakMapGetLoc, JSWeakSetFields, mapEdge, keyEdge), LazyNode(keyEdge.node()));
1766 return;
1767 }
1768
1769 case WeakMapSet: {
1770 Edge& mapEdge = graph.varArgChild(node, 0);
1771 Edge& keyEdge = graph.varArgChild(node, 1);
1772 Edge& valueEdge = graph.varArgChild(node, 2);
1773 write(JSWeakMapFields);
1774 def(HeapLocation(WeakMapGetLoc, JSWeakMapFields, mapEdge, keyEdge), LazyNode(valueEdge.node()));
1775 return;
1776 }
1777
1778 case ExtractValueFromWeakMapGet:
1779 def(PureValue(node));
1780 return;
1781
1782 case StringSlice:
1783 def(PureValue(node));
1784 return;
1785
1786 case ToLowerCase:
1787 def(PureValue(node));
1788 return;
1789
1790 case NumberToStringWithValidRadixConstant:
1791 def(PureValue(node, node->validRadixConstant()));
1792 return;
1793
1794 case DataViewGetFloat:
1795 case DataViewGetInt: {
1796 read(MiscFields);
1797 read(TypedArrayProperties);
1798 LocationKind indexedPropertyLoc = indexedPropertyLocForResultType(node->result());
1799 def(HeapLocation(indexedPropertyLoc, AbstractHeap(TypedArrayProperties, node->dataViewData().asQuadWord),
1800 node->child1(), node->child2(), node->child3()), LazyNode(node));
1801 return;
1802 }
1803
1804 case DataViewSet: {
1805 read(MiscFields);
1806 read(TypedArrayProperties);
1807 write(TypedArrayProperties);
1808 return;
1809 }
1810
1811 case LastNodeType:
1812 RELEASE_ASSERT_NOT_REACHED();
1813 return;
1814 }
1815
1816 DFG_CRASH(graph, node, toCString("Unrecognized node type: ", Graph::opName(node->op())).data());
1817}
1818
1819class NoOpClobberize {
1820public:
1821 NoOpClobberize() { }
1822 template<typename... T>
1823 void operator()(T...) const { }
1824};
1825
1826class CheckClobberize {
1827public:
1828 CheckClobberize()
1829 : m_result(false)
1830 {
1831 }
1832
1833 template<typename... T>
1834 void operator()(T...) const { m_result = true; }
1835
1836 bool result() const { return m_result; }
1837
1838private:
1839 mutable bool m_result;
1840};
1841
1842bool doesWrites(Graph&, Node*);
1843
1844class AbstractHeapOverlaps {
1845public:
1846 AbstractHeapOverlaps(AbstractHeap heap)
1847 : m_heap(heap)
1848 , m_result(false)
1849 {
1850 }
1851
1852 void operator()(AbstractHeap otherHeap) const
1853 {
1854 if (m_result)
1855 return;
1856 m_result = m_heap.overlaps(otherHeap);
1857 }
1858
1859 bool result() const { return m_result; }
1860
1861private:
1862 AbstractHeap m_heap;
1863 mutable bool m_result;
1864};
1865
1866bool accessesOverlap(Graph&, Node*, AbstractHeap);
1867bool writesOverlap(Graph&, Node*, AbstractHeap);
1868
1869bool clobbersHeap(Graph&, Node*);
1870
1871// We would have used bind() for these, but because of the overlaoding that we are doing,
1872// it's quite a bit of clearer to just write this out the traditional way.
1873
1874template<typename T>
1875class ReadMethodClobberize {
1876public:
1877 ReadMethodClobberize(T& value)
1878 : m_value(value)
1879 {
1880 }
1881
1882 void operator()(AbstractHeap heap) const
1883 {
1884 m_value.read(heap);
1885 }
1886private:
1887 T& m_value;
1888};
1889
1890template<typename T>
1891class WriteMethodClobberize {
1892public:
1893 WriteMethodClobberize(T& value)
1894 : m_value(value)
1895 {
1896 }
1897
1898 void operator()(AbstractHeap heap) const
1899 {
1900 m_value.write(heap);
1901 }
1902private:
1903 T& m_value;
1904};
1905
1906template<typename T>
1907class DefMethodClobberize {
1908public:
1909 DefMethodClobberize(T& value)
1910 : m_value(value)
1911 {
1912 }
1913
1914 void operator()(PureValue value) const
1915 {
1916 m_value.def(value);
1917 }
1918
1919 void operator()(HeapLocation location, LazyNode node) const
1920 {
1921 m_value.def(location, node);
1922 }
1923
1924private:
1925 T& m_value;
1926};
1927
1928template<typename Adaptor>
1929void clobberize(Graph& graph, Node* node, Adaptor& adaptor)
1930{
1931 ReadMethodClobberize<Adaptor> read(adaptor);
1932 WriteMethodClobberize<Adaptor> write(adaptor);
1933 DefMethodClobberize<Adaptor> def(adaptor);
1934 clobberize(graph, node, read, write, def);
1935}
1936
1937} } // namespace JSC::DFG
1938
1939#endif // ENABLE(DFG_JIT)
1940