8a2986b89d850342aadeb5aa98214aac1a4f29d0
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGAbstractInterpreterInlines.h
1 /*
2  * Copyright (C) 2013-2017 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 "ArrayConstructor.h"
31 #include "DFGAbstractInterpreter.h"
32 #include "DOMJITGetterSetter.h"
33 #include "DOMJITSignature.h"
34 #include "GetByIdStatus.h"
35 #include "GetterSetter.h"
36 #include "HashMapImpl.h"
37 #include "JITOperations.h"
38 #include "MathCommon.h"
39 #include "Operations.h"
40 #include "PutByIdStatus.h"
41 #include "StringObject.h"
42
43 namespace JSC { namespace DFG {
44
45 template<typename AbstractStateType>
46 AbstractInterpreter<AbstractStateType>::AbstractInterpreter(Graph& graph, AbstractStateType& state)
47     : m_codeBlock(graph.m_codeBlock)
48     , m_graph(graph)
49     , m_vm(m_graph.m_vm)
50     , m_state(state)
51 {
52     if (m_graph.m_form == SSA)
53         m_phiChildren = std::make_unique<PhiChildren>(m_graph);
54 }
55
56 template<typename AbstractStateType>
57 AbstractInterpreter<AbstractStateType>::~AbstractInterpreter()
58 {
59 }
60
61 template<typename AbstractStateType>
62 typename AbstractInterpreter<AbstractStateType>::BooleanResult
63 AbstractInterpreter<AbstractStateType>::booleanResult(
64     Node* node, AbstractValue& value)
65 {
66     JSValue childConst = value.value();
67     if (childConst) {
68         if (childConst.toBoolean(m_codeBlock->globalObjectFor(node->origin.semantic)->globalExec()))
69             return DefinitelyTrue;
70         return DefinitelyFalse;
71     }
72
73     // Next check if we can fold because we know that the source is an object or string and does not equal undefined.
74     if (isCellSpeculation(value.m_type) && !value.m_structure.isTop()) {
75         bool allTrue = true;
76         for (unsigned i = value.m_structure.size(); i--;) {
77             RegisteredStructure structure = value.m_structure[i];
78             if (structure->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node->origin.semantic))
79                 || structure->typeInfo().type() == StringType) {
80                 allTrue = false;
81                 break;
82             }
83         }
84         if (allTrue)
85             return DefinitelyTrue;
86     }
87     
88     return UnknownBooleanResult;
89 }
90
91 template<typename AbstractStateType>
92 void AbstractInterpreter<AbstractStateType>::startExecuting()
93 {
94     ASSERT(m_state.block());
95     ASSERT(m_state.isValid());
96     
97     m_state.setDidClobber(false);
98 }
99
100 template<typename AbstractStateType>
101 void AbstractInterpreter<AbstractStateType>::executeEdges(Node* node)
102 {
103     m_graph.doToChildren(
104         node,
105         [&] (Edge& edge) {
106             filterEdgeByUse(edge);
107         });
108 }
109
110 template<typename AbstractStateType>
111 void AbstractInterpreter<AbstractStateType>::executeKnownEdgeTypes(Node* node)
112 {
113     // Some use kinds are required to not have checks, because we know somehow that the incoming
114     // value will already have the type we want. In those cases, AI may not be smart enough to
115     // prove that this is indeed the case. But the existance of the edge is enough to prove that
116     // it is indeed the case. Taking advantage of this is not optional, since otherwise the DFG
117     // and FTL backends may emit checks in a node that lacks a valid exit origin.
118     m_graph.doToChildren(
119         node,
120         [&] (Edge& edge) {
121             if (mayHaveTypeCheck(edge.useKind()))
122                 return;
123             
124             filterEdgeByUse(edge);
125         });
126 }
127
128 template<typename AbstractStateType>
129 void AbstractInterpreter<AbstractStateType>::verifyEdge(Node* node, Edge edge)
130 {
131     if (!(forNode(edge).m_type & ~typeFilterFor(edge.useKind())))
132         return;
133     
134     DFG_CRASH(m_graph, node, toCString("Edge verification error: ", node, "->", edge, " was expected to have type ", SpeculationDump(typeFilterFor(edge.useKind())), " but has type ", SpeculationDump(forNode(edge).m_type), " (", forNode(edge).m_type, ")").data(), AbstractInterpreterInvalidType, node->op(), edge->op(), edge.useKind(), forNode(edge).m_type);
135 }
136
137 template<typename AbstractStateType>
138 void AbstractInterpreter<AbstractStateType>::verifyEdges(Node* node)
139 {
140     DFG_NODE_DO_TO_CHILDREN(m_graph, node, verifyEdge);
141 }
142
143 inline bool isToThisAnIdentity(bool isStrictMode, AbstractValue& valueForNode)
144 {
145     // We look at the type first since that will cover most cases and does not require iterating all the structures.
146     if (isStrictMode) {
147         if (valueForNode.m_type && !(valueForNode.m_type & SpecObjectOther))
148             return true;
149     } else {
150         if (valueForNode.m_type && !(valueForNode.m_type & (~SpecObject | SpecObjectOther)))
151             return true;
152     }
153
154     if ((isStrictMode || (valueForNode.m_type && !(valueForNode.m_type & ~SpecObject))) && valueForNode.m_structure.isFinite()) {
155         bool overridesToThis = false;
156         valueForNode.m_structure.forEach([&](RegisteredStructure structure) {
157             TypeInfo type = structure->typeInfo();
158             ASSERT(type.isObject() || type.type() == StringType || type.type() == SymbolType);
159             if (!isStrictMode)
160                 ASSERT(type.isObject());
161             // We don't need to worry about strings/symbols here since either:
162             // 1) We are in strict mode and strings/symbols are not wrapped
163             // 2) The AI has proven that the type of this is a subtype of object
164             if (type.isObject() && type.overridesToThis())
165                 overridesToThis = true;
166         });
167         return !overridesToThis;
168     }
169
170     return false;
171 }
172
173 template<typename AbstractStateType>
174 bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimit, Node* node)
175 {
176     verifyEdges(node);
177     
178     m_state.createValueForNode(node);
179     
180     switch (node->op()) {
181     case JSConstant:
182     case DoubleConstant:
183     case Int52Constant: {
184         setBuiltInConstant(node, *node->constant());
185         break;
186     }
187
188     case LazyJSConstant: {
189         LazyJSValue value = node->lazyJSValue();
190         switch (value.kind()) {
191         case LazyJSValue::KnownValue:
192             setConstant(node, value.value()->value());
193             break;
194         case LazyJSValue::SingleCharacterString:
195         case LazyJSValue::KnownStringImpl:
196         case LazyJSValue::NewStringImpl:
197             forNode(node).setType(m_graph, SpecString);
198             break;
199         }
200         break;
201     }
202
203     case IdentityWithProfile:
204     case Identity: {
205         forNode(node) = forNode(node->child1());
206         if (forNode(node).value())
207             m_state.setFoundConstants(true);
208         break;
209     }
210         
211     case ExtractOSREntryLocal: {
212         forNode(node).makeBytecodeTop();
213         break;
214     }
215             
216     case GetLocal: {
217         VariableAccessData* variableAccessData = node->variableAccessData();
218         AbstractValue value = m_state.variables().operand(variableAccessData->local().offset());
219         // The value in the local should already be checked.
220         DFG_ASSERT(m_graph, node, value.isType(typeFilterFor(variableAccessData->flushFormat())));
221         if (value.value())
222             m_state.setFoundConstants(true);
223         forNode(node) = value;
224         break;
225     }
226         
227     case GetStack: {
228         StackAccessData* data = node->stackAccessData();
229         AbstractValue value = m_state.variables().operand(data->local);
230         // The value in the local should already be checked.
231         DFG_ASSERT(m_graph, node, value.isType(typeFilterFor(data->format)));
232         if (value.value())
233             m_state.setFoundConstants(true);
234         forNode(node) = value;
235         break;
236     }
237         
238     case GetLocalUnlinked: {
239         AbstractValue value = m_state.variables().operand(node->unlinkedLocal().offset());
240         if (value.value())
241             m_state.setFoundConstants(true);
242         forNode(node) = value;
243         break;
244     }
245         
246     case SetLocal: {
247         m_state.variables().operand(node->local()) = forNode(node->child1());
248         break;
249     }
250         
251     case PutStack: {
252         m_state.variables().operand(node->stackAccessData()->local) = forNode(node->child1());
253         break;
254     }
255         
256     case MovHint: {
257         // Don't need to do anything. A MovHint only informs us about what would have happened
258         // in bytecode, but this code is just concerned with what is actually happening during
259         // DFG execution.
260         break;
261     }
262         
263     case KillStack: {
264         // This is just a hint telling us that the OSR state of the local is no longer inside the
265         // flushed data.
266         break;
267     }
268         
269     case SetArgument:
270         // Assert that the state of arguments has been set. SetArgument means that someone set
271         // the argument values out-of-band, and currently this always means setting to a
272         // non-clear value.
273         ASSERT(!m_state.variables().operand(node->local()).isClear());
274         break;
275         
276     case LoadVarargs:
277     case ForwardVarargs: {
278         // FIXME: ForwardVarargs should check if the count becomes known, and if it does, it should turn
279         // itself into a straight-line sequence of GetStack/PutStack.
280         // https://bugs.webkit.org/show_bug.cgi?id=143071
281         clobberWorld(node->origin.semantic, clobberLimit);
282         LoadVarargsData* data = node->loadVarargsData();
283         m_state.variables().operand(data->count).setType(SpecInt32Only);
284         for (unsigned i = data->limit - 1; i--;)
285             m_state.variables().operand(data->start.offset() + i).makeHeapTop();
286         break;
287     }
288             
289     case BitAnd:
290     case BitOr:
291     case BitXor:
292     case BitRShift:
293     case BitLShift:
294     case BitURShift: {
295         if (node->child1().useKind() == UntypedUse || node->child2().useKind() == UntypedUse) {
296             clobberWorld(node->origin.semantic, clobberLimit);
297             forNode(node).setType(m_graph, SpecInt32Only);
298             break;
299         }
300
301         JSValue left = forNode(node->child1()).value();
302         JSValue right = forNode(node->child2()).value();
303         if (left && right && left.isInt32() && right.isInt32()) {
304             int32_t a = left.asInt32();
305             int32_t b = right.asInt32();
306             switch (node->op()) {
307             case BitAnd:
308                 setConstant(node, JSValue(a & b));
309                 break;
310             case BitOr:
311                 setConstant(node, JSValue(a | b));
312                 break;
313             case BitXor:
314                 setConstant(node, JSValue(a ^ b));
315                 break;
316             case BitRShift:
317                 setConstant(node, JSValue(a >> static_cast<uint32_t>(b)));
318                 break;
319             case BitLShift:
320                 setConstant(node, JSValue(a << static_cast<uint32_t>(b)));
321                 break;
322             case BitURShift:
323                 setConstant(node, JSValue(static_cast<uint32_t>(a) >> static_cast<uint32_t>(b)));
324                 break;
325             default:
326                 RELEASE_ASSERT_NOT_REACHED();
327                 break;
328             }
329             break;
330         }
331         
332         if (node->op() == BitAnd
333             && (isBoolInt32Speculation(forNode(node->child1()).m_type) ||
334                 isBoolInt32Speculation(forNode(node->child2()).m_type))) {
335             forNode(node).setType(SpecBoolInt32);
336             break;
337         }
338         
339         forNode(node).setType(SpecInt32Only);
340         break;
341     }
342         
343     case UInt32ToNumber: {
344         JSValue child = forNode(node->child1()).value();
345         if (doesOverflow(node->arithMode())) {
346             if (enableInt52()) {
347                 if (child && child.isAnyInt()) {
348                     int64_t machineInt = child.asAnyInt();
349                     setConstant(node, jsNumber(static_cast<uint32_t>(machineInt)));
350                     break;
351                 }
352                 forNode(node).setType(SpecAnyInt);
353                 break;
354             }
355             if (child && child.isInt32()) {
356                 uint32_t value = child.asInt32();
357                 setConstant(node, jsNumber(value));
358                 break;
359             }
360             forNode(node).setType(SpecAnyIntAsDouble);
361             break;
362         }
363         if (child && child.isInt32()) {
364             int32_t value = child.asInt32();
365             if (value >= 0) {
366                 setConstant(node, jsNumber(value));
367                 break;
368             }
369         }
370         forNode(node).setType(SpecInt32Only);
371         break;
372     }
373         
374     case BooleanToNumber: {
375         JSValue concreteValue = forNode(node->child1()).value();
376         if (concreteValue) {
377             if (concreteValue.isBoolean())
378                 setConstant(node, jsNumber(concreteValue.asBoolean()));
379             else
380                 setConstant(node, *m_graph.freeze(concreteValue));
381             break;
382         }
383         AbstractValue& value = forNode(node);
384         value = forNode(node->child1());
385         if (node->child1().useKind() == UntypedUse && !(value.m_type & ~SpecBoolean))
386             m_state.setFoundConstants(true);
387         if (value.m_type & SpecBoolean) {
388             value.merge(SpecBoolInt32);
389             value.filter(~SpecBoolean);
390         }
391         break;
392     }
393             
394     case DoubleAsInt32: {
395         JSValue child = forNode(node->child1()).value();
396         if (child && child.isNumber()) {
397             double asDouble = child.asNumber();
398             int32_t asInt = JSC::toInt32(asDouble);
399             if (bitwise_cast<int64_t>(static_cast<double>(asInt)) == bitwise_cast<int64_t>(asDouble)) {
400                 setConstant(node, JSValue(asInt));
401                 break;
402             }
403         }
404         forNode(node).setType(SpecInt32Only);
405         break;
406     }
407             
408     case ValueToInt32: {
409         JSValue child = forNode(node->child1()).value();
410         if (child) {
411             if (child.isNumber()) {
412                 if (child.isInt32())
413                     setConstant(node, child);
414                 else
415                     setConstant(node, JSValue(JSC::toInt32(child.asDouble())));
416                 break;
417             }
418             if (child.isBoolean()) {
419                 setConstant(node, jsNumber(child.asBoolean()));
420                 break;
421             }
422             if (child.isUndefinedOrNull()) {
423                 setConstant(node, jsNumber(0));
424                 break;
425             }
426         }
427         
428         if (isBooleanSpeculation(forNode(node->child1()).m_type)) {
429             forNode(node).setType(SpecBoolInt32);
430             break;
431         }
432         
433         forNode(node).setType(SpecInt32Only);
434         break;
435     }
436         
437     case DoubleRep: {
438         JSValue child = forNode(node->child1()).value();
439         if (std::optional<double> number = child.toNumberFromPrimitive()) {
440             setConstant(node, jsDoubleNumber(*number));
441             break;
442         }
443
444         SpeculatedType type = forNode(node->child1()).m_type;
445         switch (node->child1().useKind()) {
446         case NotCellUse: {
447             if (type & SpecOther) {
448                 type &= ~SpecOther;
449                 type |= SpecDoublePureNaN | SpecBoolInt32; // Null becomes zero, undefined becomes NaN.
450             }
451             if (type & SpecBoolean) {
452                 type &= ~SpecBoolean;
453                 type |= SpecBoolInt32; // True becomes 1, false becomes 0.
454             }
455             type &= SpecBytecodeNumber;
456             break;
457         }
458
459         case Int52RepUse:
460         case NumberUse:
461         case RealNumberUse:
462             break;
463
464         default:
465             RELEASE_ASSERT_NOT_REACHED();
466         }
467         forNode(node).setType(type);
468         forNode(node).fixTypeForRepresentation(m_graph, node);
469         break;
470     }
471         
472     case Int52Rep: {
473         JSValue child = forNode(node->child1()).value();
474         if (child && child.isAnyInt()) {
475             setConstant(node, child);
476             break;
477         }
478         
479         forNode(node).setType(SpecAnyInt);
480         break;
481     }
482         
483     case ValueRep: {
484         JSValue value = forNode(node->child1()).value();
485         if (value) {
486             setConstant(node, value);
487             break;
488         }
489         
490         forNode(node).setType(m_graph, forNode(node->child1()).m_type & ~SpecDoubleImpureNaN);
491         forNode(node).fixTypeForRepresentation(m_graph, node);
492         break;
493     }
494         
495     case ValueAdd: {
496         ASSERT(node->binaryUseKind() == UntypedUse);
497         clobberWorld(node->origin.semantic, clobberLimit);
498         forNode(node).setType(m_graph, SpecString | SpecBytecodeNumber);
499         break;
500     }
501
502     case StrCat: {
503         forNode(node).setType(m_graph, SpecString);
504         break;
505     }
506         
507     case ArithAdd: {
508         JSValue left = forNode(node->child1()).value();
509         JSValue right = forNode(node->child2()).value();
510         switch (node->binaryUseKind()) {
511         case Int32Use:
512             if (left && right && left.isInt32() && right.isInt32()) {
513                 if (!shouldCheckOverflow(node->arithMode())) {
514                     setConstant(node, jsNumber(left.asInt32() + right.asInt32()));
515                     break;
516                 }
517                 JSValue result = jsNumber(left.asNumber() + right.asNumber());
518                 if (result.isInt32()) {
519                     setConstant(node, result);
520                     break;
521                 }
522             }
523             forNode(node).setType(SpecInt32Only);
524             break;
525         case Int52RepUse:
526             if (left && right && left.isAnyInt() && right.isAnyInt()) {
527                 JSValue result = jsNumber(left.asAnyInt() + right.asAnyInt());
528                 if (result.isAnyInt()) {
529                     setConstant(node, result);
530                     break;
531                 }
532             }
533             forNode(node).setType(SpecAnyInt);
534             break;
535         case DoubleRepUse:
536             if (left && right && left.isNumber() && right.isNumber()) {
537                 setConstant(node, jsDoubleNumber(left.asNumber() + right.asNumber()));
538                 break;
539             }
540             forNode(node).setType(
541                 typeOfDoubleSum(
542                     forNode(node->child1()).m_type, forNode(node->child2()).m_type));
543             break;
544         default:
545             RELEASE_ASSERT_NOT_REACHED();
546             break;
547         }
548         break;
549     }
550         
551     case AtomicsIsLockFree: {
552         if (node->child1().useKind() != Int32Use)
553             clobberWorld(node->origin.semantic, clobberLimit);
554         forNode(node).setType(SpecBoolInt32);
555         break;
556     }
557
558     case ArithClz32: {
559         JSValue operand = forNode(node->child1()).value();
560         if (std::optional<double> number = operand.toNumberFromPrimitive()) {
561             uint32_t value = toUInt32(*number);
562             setConstant(node, jsNumber(clz32(value)));
563             break;
564         }
565         forNode(node).setType(SpecInt32Only);
566         break;
567     }
568
569     case MakeRope: {
570         unsigned numberOfChildren = 0;
571         unsigned numberOfRemovedChildren = 0;
572         std::optional<unsigned> nonEmptyIndex;
573         for (unsigned i = 0; i < AdjacencyList::Size; ++i) {
574             Edge& edge = node->children.child(i);
575             if (!edge)
576                 break;
577             ++numberOfChildren;
578
579             JSValue childConstant = m_state.forNode(edge).value();
580             if (!childConstant) {
581                 nonEmptyIndex = i;
582                 continue;
583             }
584             if (!childConstant.isString()) {
585                 nonEmptyIndex = i;
586                 continue;
587             }
588             if (asString(childConstant)->length()) {
589                 nonEmptyIndex = i;
590                 continue;
591             }
592
593             ++numberOfRemovedChildren;
594         }
595
596         if (numberOfRemovedChildren) {
597             m_state.setFoundConstants(true);
598             if (numberOfRemovedChildren == numberOfChildren) {
599                 // Propagate the last child. This is the way taken in the constant folding phase.
600                 forNode(node) = forNode(node->children.child(numberOfChildren - 1));
601                 break;
602             }
603             if ((numberOfRemovedChildren + 1) == numberOfChildren) {
604                 ASSERT(nonEmptyIndex);
605                 forNode(node) = forNode(node->children.child(nonEmptyIndex.value()));
606                 break;
607             }
608         }
609         forNode(node).set(m_graph, m_vm.stringStructure.get());
610         break;
611     }
612             
613     case ArithSub: {
614         JSValue left = forNode(node->child1()).value();
615         JSValue right = forNode(node->child2()).value();
616         switch (node->binaryUseKind()) {
617         case Int32Use:
618             if (left && right && left.isInt32() && right.isInt32()) {
619                 if (!shouldCheckOverflow(node->arithMode())) {
620                     setConstant(node, jsNumber(left.asInt32() - right.asInt32()));
621                     break;
622                 }
623                 JSValue result = jsNumber(left.asNumber() - right.asNumber());
624                 if (result.isInt32()) {
625                     setConstant(node, result);
626                     break;
627                 }
628             }
629             forNode(node).setType(SpecInt32Only);
630             break;
631         case Int52RepUse:
632             if (left && right && left.isAnyInt() && right.isAnyInt()) {
633                 JSValue result = jsNumber(left.asAnyInt() - right.asAnyInt());
634                 if (result.isAnyInt() || !shouldCheckOverflow(node->arithMode())) {
635                     setConstant(node, result);
636                     break;
637                 }
638             }
639             forNode(node).setType(SpecAnyInt);
640             break;
641         case DoubleRepUse:
642             if (left && right && left.isNumber() && right.isNumber()) {
643                 setConstant(node, jsDoubleNumber(left.asNumber() - right.asNumber()));
644                 break;
645             }
646             forNode(node).setType(
647                 typeOfDoubleDifference(
648                     forNode(node->child1()).m_type, forNode(node->child2()).m_type));
649             break;
650         case UntypedUse:
651             clobberWorld(node->origin.semantic, clobberLimit);
652             forNode(node).setType(m_graph, SpecBytecodeNumber);
653             break;
654         default:
655             RELEASE_ASSERT_NOT_REACHED();
656             break;
657         }
658         break;
659     }
660         
661     case ArithNegate: {
662         JSValue child = forNode(node->child1()).value();
663         switch (node->child1().useKind()) {
664         case Int32Use:
665             if (child && child.isInt32()) {
666                 if (!shouldCheckOverflow(node->arithMode())) {
667                     setConstant(node, jsNumber(-child.asInt32()));
668                     break;
669                 }
670                 double doubleResult;
671                 if (shouldCheckNegativeZero(node->arithMode()))
672                     doubleResult = -child.asNumber();
673                 else
674                     doubleResult = 0 - child.asNumber();
675                 JSValue valueResult = jsNumber(doubleResult);
676                 if (valueResult.isInt32()) {
677                     setConstant(node, valueResult);
678                     break;
679                 }
680             }
681             forNode(node).setType(SpecInt32Only);
682             break;
683         case Int52RepUse:
684             if (child && child.isAnyInt()) {
685                 double doubleResult;
686                 if (shouldCheckNegativeZero(node->arithMode()))
687                     doubleResult = -child.asNumber();
688                 else
689                     doubleResult = 0 - child.asNumber();
690                 JSValue valueResult = jsNumber(doubleResult);
691                 if (valueResult.isAnyInt()) {
692                     setConstant(node, valueResult);
693                     break;
694                 }
695             }
696             forNode(node).setType(SpecAnyInt);
697             break;
698         case DoubleRepUse:
699             if (child && child.isNumber()) {
700                 setConstant(node, jsDoubleNumber(-child.asNumber()));
701                 break;
702             }
703             forNode(node).setType(
704                 typeOfDoubleNegation(
705                     forNode(node->child1()).m_type));
706             break;
707         default:
708             DFG_ASSERT(m_graph, node, node->child1().useKind() == UntypedUse);
709             forNode(node).setType(SpecBytecodeNumber);
710             break;
711         }
712         break;
713     }
714         
715     case ArithMul: {
716         JSValue left = forNode(node->child1()).value();
717         JSValue right = forNode(node->child2()).value();
718         switch (node->binaryUseKind()) {
719         case Int32Use:
720             if (left && right && left.isInt32() && right.isInt32()) {
721                 if (!shouldCheckOverflow(node->arithMode())) {
722                     setConstant(node, jsNumber(left.asInt32() * right.asInt32()));
723                     break;
724                 }
725                 double doubleResult = left.asNumber() * right.asNumber();
726                 if (!shouldCheckNegativeZero(node->arithMode()))
727                     doubleResult += 0; // Sanitizes zero.
728                 JSValue valueResult = jsNumber(doubleResult);
729                 if (valueResult.isInt32()) {
730                     setConstant(node, valueResult);
731                     break;
732                 }
733             }
734             forNode(node).setType(SpecInt32Only);
735             break;
736         case Int52RepUse:
737             if (left && right && left.isAnyInt() && right.isAnyInt()) {
738                 double doubleResult = left.asNumber() * right.asNumber();
739                 if (!shouldCheckNegativeZero(node->arithMode()))
740                     doubleResult += 0;
741                 JSValue valueResult = jsNumber(doubleResult);
742                 if (valueResult.isAnyInt()) {
743                     setConstant(node, valueResult);
744                     break;
745                 }
746             }
747             forNode(node).setType(SpecAnyInt);
748             break;
749         case DoubleRepUse:
750             if (left && right && left.isNumber() && right.isNumber()) {
751                 setConstant(node, jsDoubleNumber(left.asNumber() * right.asNumber()));
752                 break;
753             }
754             forNode(node).setType(
755                 typeOfDoubleProduct(
756                     forNode(node->child1()).m_type, forNode(node->child2()).m_type));
757             break;
758         case UntypedUse:
759             clobberWorld(node->origin.semantic, clobberLimit);
760             forNode(node).setType(m_graph, SpecBytecodeNumber);
761             break;
762         default:
763             RELEASE_ASSERT_NOT_REACHED();
764             break;
765         }
766         break;
767     }
768         
769     case ArithDiv: {
770         JSValue left = forNode(node->child1()).value();
771         JSValue right = forNode(node->child2()).value();
772         switch (node->binaryUseKind()) {
773         case Int32Use:
774             if (left && right && left.isInt32() && right.isInt32()) {
775                 double doubleResult = left.asNumber() / right.asNumber();
776                 if (!shouldCheckOverflow(node->arithMode()))
777                     doubleResult = toInt32(doubleResult);
778                 else if (!shouldCheckNegativeZero(node->arithMode()))
779                     doubleResult += 0; // Sanitizes zero.
780                 JSValue valueResult = jsNumber(doubleResult);
781                 if (valueResult.isInt32()) {
782                     setConstant(node, valueResult);
783                     break;
784                 }
785             }
786             forNode(node).setType(SpecInt32Only);
787             break;
788         case DoubleRepUse:
789             if (left && right && left.isNumber() && right.isNumber()) {
790                 setConstant(node, jsDoubleNumber(left.asNumber() / right.asNumber()));
791                 break;
792             }
793             forNode(node).setType(
794                 typeOfDoubleQuotient(
795                     forNode(node->child1()).m_type, forNode(node->child2()).m_type));
796             break;
797         case UntypedUse:
798             clobberWorld(node->origin.semantic, clobberLimit);
799             forNode(node).setType(m_graph, SpecBytecodeNumber);
800             break;
801         default:
802             RELEASE_ASSERT_NOT_REACHED();
803             break;
804         }
805         break;
806     }
807
808     case ArithMod: {
809         JSValue left = forNode(node->child1()).value();
810         JSValue right = forNode(node->child2()).value();
811         switch (node->binaryUseKind()) {
812         case Int32Use:
813             if (left && right && left.isInt32() && right.isInt32()) {
814                 double doubleResult = fmod(left.asNumber(), right.asNumber());
815                 if (!shouldCheckOverflow(node->arithMode()))
816                     doubleResult = toInt32(doubleResult);
817                 else if (!shouldCheckNegativeZero(node->arithMode()))
818                     doubleResult += 0; // Sanitizes zero.
819                 JSValue valueResult = jsNumber(doubleResult);
820                 if (valueResult.isInt32()) {
821                     setConstant(node, valueResult);
822                     break;
823                 }
824             }
825             forNode(node).setType(SpecInt32Only);
826             break;
827         case DoubleRepUse:
828             if (left && right && left.isNumber() && right.isNumber()) {
829                 setConstant(node, jsDoubleNumber(fmod(left.asNumber(), right.asNumber())));
830                 break;
831             }
832             forNode(node).setType(
833                 typeOfDoubleBinaryOp(
834                     forNode(node->child1()).m_type, forNode(node->child2()).m_type));
835             break;
836         default:
837             RELEASE_ASSERT_NOT_REACHED();
838             break;
839         }
840         break;
841     }
842
843     case ArithMin: {
844         JSValue left = forNode(node->child1()).value();
845         JSValue right = forNode(node->child2()).value();
846         switch (node->binaryUseKind()) {
847         case Int32Use:
848             if (left && right && left.isInt32() && right.isInt32()) {
849                 setConstant(node, jsNumber(std::min(left.asInt32(), right.asInt32())));
850                 break;
851             }
852             forNode(node).setType(SpecInt32Only);
853             break;
854         case DoubleRepUse:
855             if (left && right && left.isNumber() && right.isNumber()) {
856                 double a = left.asNumber();
857                 double b = right.asNumber();
858                 setConstant(node, jsDoubleNumber(a < b ? a : (b <= a ? b : a + b)));
859                 break;
860             }
861             forNode(node).setType(
862                 typeOfDoubleMinMax(
863                     forNode(node->child1()).m_type, forNode(node->child2()).m_type));
864             break;
865         default:
866             RELEASE_ASSERT_NOT_REACHED();
867             break;
868         }
869         break;
870     }
871             
872     case ArithMax: {
873         JSValue left = forNode(node->child1()).value();
874         JSValue right = forNode(node->child2()).value();
875         switch (node->binaryUseKind()) {
876         case Int32Use:
877             if (left && right && left.isInt32() && right.isInt32()) {
878                 setConstant(node, jsNumber(std::max(left.asInt32(), right.asInt32())));
879                 break;
880             }
881             forNode(node).setType(SpecInt32Only);
882             break;
883         case DoubleRepUse:
884             if (left && right && left.isNumber() && right.isNumber()) {
885                 double a = left.asNumber();
886                 double b = right.asNumber();
887                 setConstant(node, jsDoubleNumber(a > b ? a : (b >= a ? b : a + b)));
888                 break;
889             }
890             forNode(node).setType(
891                 typeOfDoubleMinMax(
892                     forNode(node->child1()).m_type, forNode(node->child2()).m_type));
893             break;
894         default:
895             RELEASE_ASSERT_NOT_REACHED();
896             break;
897         }
898         break;
899     }
900             
901     case ArithAbs: {
902         JSValue child = forNode(node->child1()).value();
903         switch (node->child1().useKind()) {
904         case Int32Use:
905             if (std::optional<double> number = child.toNumberFromPrimitive()) {
906                 JSValue result = jsNumber(fabs(*number));
907                 if (result.isInt32()) {
908                     setConstant(node, result);
909                     break;
910                 }
911             }
912             forNode(node).setType(SpecInt32Only);
913             break;
914         case DoubleRepUse:
915             if (std::optional<double> number = child.toNumberFromPrimitive()) {
916                 setConstant(node, jsDoubleNumber(fabs(*number)));
917                 break;
918             }
919             forNode(node).setType(typeOfDoubleAbs(forNode(node->child1()).m_type));
920             break;
921         default:
922             DFG_ASSERT(m_graph, node, node->child1().useKind() == UntypedUse);
923             forNode(node).setType(SpecFullNumber);
924             break;
925         }
926         break;
927     }
928
929     case ArithPow: {
930         JSValue childY = forNode(node->child2()).value();
931         if (childY && childY.isNumber()) {
932             if (!childY.asNumber()) {
933                 setConstant(node, jsDoubleNumber(1));
934                 break;
935             }
936
937             JSValue childX = forNode(node->child1()).value();
938             if (childX && childX.isNumber()) {
939                 setConstant(node, jsDoubleNumber(operationMathPow(childX.asNumber(), childY.asNumber())));
940                 break;
941             }
942         }
943         forNode(node).setType(typeOfDoublePow(forNode(node->child1()).m_type, forNode(node->child2()).m_type));
944         break;
945     }
946
947     case ArithRandom: {
948         forNode(node).setType(m_graph, SpecDoubleReal);
949         break;
950     }
951
952     case ArithRound:
953     case ArithFloor:
954     case ArithCeil:
955     case ArithTrunc: {
956         JSValue operand = forNode(node->child1()).value();
957         if (std::optional<double> number = operand.toNumberFromPrimitive()) {
958             double roundedValue = 0;
959             if (node->op() == ArithRound)
960                 roundedValue = jsRound(*number);
961             else if (node->op() == ArithFloor)
962                 roundedValue = floor(*number);
963             else if (node->op() == ArithCeil)
964                 roundedValue = ceil(*number);
965             else {
966                 ASSERT(node->op() == ArithTrunc);
967                 roundedValue = trunc(*number);
968             }
969
970             if (node->child1().useKind() == UntypedUse) {
971                 setConstant(node, jsNumber(roundedValue));
972                 break;
973             }
974             if (producesInteger(node->arithRoundingMode())) {
975                 int32_t roundedValueAsInt32 = static_cast<int32_t>(roundedValue);
976                 if (roundedValueAsInt32 == roundedValue) {
977                     if (shouldCheckNegativeZero(node->arithRoundingMode())) {
978                         if (roundedValueAsInt32 || !std::signbit(roundedValue)) {
979                             setConstant(node, jsNumber(roundedValueAsInt32));
980                             break;
981                         }
982                     } else {
983                         setConstant(node, jsNumber(roundedValueAsInt32));
984                         break;
985                     }
986                 }
987             } else {
988                 setConstant(node, jsDoubleNumber(roundedValue));
989                 break;
990             }
991         }
992         if (node->child1().useKind() == DoubleRepUse) {
993             if (producesInteger(node->arithRoundingMode()))
994                 forNode(node).setType(SpecInt32Only);
995             else if (node->child1().useKind() == DoubleRepUse)
996                 forNode(node).setType(typeOfDoubleRounding(forNode(node->child1()).m_type));
997         } else {
998             DFG_ASSERT(m_graph, node, node->child1().useKind() == UntypedUse);
999             forNode(node).setType(SpecFullNumber);
1000         }
1001         break;
1002     }
1003             
1004     case ArithSqrt:
1005         executeDoubleUnaryOpEffects(node, sqrt);
1006         break;
1007
1008     case ArithFRound:
1009         executeDoubleUnaryOpEffects(node, [](double value) -> double { return static_cast<float>(value); });
1010         break;
1011         
1012     case ArithUnary:
1013         executeDoubleUnaryOpEffects(node, arithUnaryFunction(node->arithUnaryType()));
1014         break;
1015             
1016     case LogicalNot: {
1017         switch (booleanResult(node, forNode(node->child1()))) {
1018         case DefinitelyTrue:
1019             setConstant(node, jsBoolean(false));
1020             break;
1021         case DefinitelyFalse:
1022             setConstant(node, jsBoolean(true));
1023             break;
1024         default:
1025             forNode(node).setType(SpecBoolean);
1026             break;
1027         }
1028         break;
1029     }
1030
1031     case MapHash: {
1032         if (JSValue key = forNode(node->child1()).value()) {
1033             if (std::optional<uint32_t> hash = concurrentJSMapHash(key)) {
1034                 // Although C++ code uses uint32_t for the hash, the closest type in DFG IR is Int32
1035                 // and that's what MapHash returns. So, we have to cast to int32_t to avoid large
1036                 // unsigned values becoming doubles. This casting between signed and unsigned
1037                 // happens in the assembly code we emit when we don't constant fold this node.
1038                 setConstant(node, jsNumber(static_cast<int32_t>(*hash)));
1039                 break;
1040             }
1041         }
1042         forNode(node).setType(SpecInt32Only);
1043         break;
1044     }
1045
1046     case ToLowerCase: {
1047         forNode(node).setType(m_graph, SpecString);
1048         break;
1049     }
1050
1051     case LoadFromJSMapBucket:
1052         forNode(node).makeHeapTop();
1053         break;
1054
1055     case GetMapBucket:
1056         forNode(node).setType(m_graph, SpecCellOther);
1057         break;
1058
1059     case IsNonEmptyMapBucket:
1060         forNode(node).setType(SpecBoolean);
1061         break;
1062
1063     case IsEmpty:
1064     case IsUndefined:
1065     case IsBoolean:
1066     case IsNumber:
1067     case IsObject:
1068     case IsObjectOrNull:
1069     case IsFunction:
1070     case IsCellWithType:
1071     case IsTypedArrayView: {
1072         AbstractValue child = forNode(node->child1());
1073         if (child.value()) {
1074             bool constantWasSet = true;
1075             switch (node->op()) {
1076             case IsCellWithType:
1077                 setConstant(node, jsBoolean(child.value().isCell() && child.value().asCell()->type() == node->queriedType()));
1078                 break;
1079             case IsUndefined:
1080                 setConstant(node, jsBoolean(
1081                     child.value().isCell()
1082                     ? child.value().asCell()->structure()->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node->origin.semantic))
1083                     : child.value().isUndefined()));
1084                 break;
1085             case IsBoolean:
1086                 setConstant(node, jsBoolean(child.value().isBoolean()));
1087                 break;
1088             case IsNumber:
1089                 setConstant(node, jsBoolean(child.value().isNumber()));
1090                 break;
1091             case IsObject:
1092                 setConstant(node, jsBoolean(child.value().isObject()));
1093                 break;
1094             case IsObjectOrNull:
1095                 if (child.value().isObject()) {
1096                     JSObject* object = asObject(child.value());
1097                     if (object->type() == JSFunctionType)
1098                         setConstant(node, jsBoolean(false));
1099                     else if (!(object->inlineTypeFlags() & TypeOfShouldCallGetCallData))
1100                         setConstant(node, jsBoolean(!child.value().asCell()->structure()->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node->origin.semantic))));
1101                     else {
1102                         // FIXME: This could just call getCallData.
1103                         // https://bugs.webkit.org/show_bug.cgi?id=144457
1104                         constantWasSet = false;
1105                     }
1106                 } else
1107                     setConstant(node, jsBoolean(child.value().isNull()));
1108                 break;
1109             case IsFunction:
1110                 if (child.value().isObject()) {
1111                     JSObject* object = asObject(child.value());
1112                     if (object->type() == JSFunctionType)
1113                         setConstant(node, jsBoolean(true));
1114                     else if (!(object->inlineTypeFlags() & TypeOfShouldCallGetCallData))
1115                         setConstant(node, jsBoolean(false));
1116                     else {
1117                         // FIXME: This could just call getCallData.
1118                         // https://bugs.webkit.org/show_bug.cgi?id=144457
1119                         constantWasSet = false;
1120                     }
1121                 } else
1122                     setConstant(node, jsBoolean(false));
1123                 break;
1124             case IsEmpty:
1125                 setConstant(node, jsBoolean(child.value().isEmpty()));
1126                 break;
1127             case IsTypedArrayView:
1128                 setConstant(node, jsBoolean(child.value().isObject() && isTypedView(child.value().getObject()->classInfo(m_vm)->typedArrayStorageType)));
1129                 break;
1130             default:
1131                 constantWasSet = false;
1132                 break;
1133             }
1134             if (constantWasSet)
1135                 break;
1136         }
1137         
1138         // FIXME: This code should really use AbstractValue::isType() and
1139         // AbstractValue::couldBeType().
1140         // https://bugs.webkit.org/show_bug.cgi?id=146870
1141         
1142         bool constantWasSet = false;
1143         switch (node->op()) {
1144         case IsEmpty: {
1145             if (child.m_type && !(child.m_type & SpecEmpty)) {
1146                 setConstant(node, jsBoolean(false));
1147                 constantWasSet = true;
1148                 break;
1149             }
1150
1151             if (child.m_type && !(child.m_type & ~SpecEmpty)) {
1152                 setConstant(node, jsBoolean(true));
1153                 constantWasSet = true;
1154                 break;
1155             }
1156
1157             break;
1158         }
1159         case IsUndefined:
1160             // FIXME: Use the masquerades-as-undefined watchpoint thingy.
1161             // https://bugs.webkit.org/show_bug.cgi?id=144456
1162             
1163             if (!(child.m_type & (SpecOther | SpecObjectOther))) {
1164                 setConstant(node, jsBoolean(false));
1165                 constantWasSet = true;
1166                 break;
1167             }
1168             
1169             break;
1170         case IsBoolean:
1171             if (!(child.m_type & ~SpecBoolean)) {
1172                 setConstant(node, jsBoolean(true));
1173                 constantWasSet = true;
1174                 break;
1175             }
1176             
1177             if (!(child.m_type & SpecBoolean)) {
1178                 setConstant(node, jsBoolean(false));
1179                 constantWasSet = true;
1180                 break;
1181             }
1182             
1183             break;
1184         case IsNumber:
1185             if (!(child.m_type & ~SpecFullNumber)) {
1186                 setConstant(node, jsBoolean(true));
1187                 constantWasSet = true;
1188                 break;
1189             }
1190             
1191             if (!(child.m_type & SpecFullNumber)) {
1192                 setConstant(node, jsBoolean(false));
1193                 constantWasSet = true;
1194                 break;
1195             }
1196             
1197             break;
1198         case IsObject:
1199             if (!(child.m_type & ~SpecObject)) {
1200                 setConstant(node, jsBoolean(true));
1201                 constantWasSet = true;
1202                 break;
1203             }
1204             
1205             if (!(child.m_type & SpecObject)) {
1206                 setConstant(node, jsBoolean(false));
1207                 constantWasSet = true;
1208                 break;
1209             }
1210             
1211             break;
1212         case IsObjectOrNull:
1213             // FIXME: Use the masquerades-as-undefined watchpoint thingy.
1214             // https://bugs.webkit.org/show_bug.cgi?id=144456
1215             
1216             // These expressions are complicated to parse. A helpful way to parse this is that
1217             // "!(T & ~S)" means "T is a subset of S". Conversely, "!(T & S)" means "T is a
1218             // disjoint set from S". Things like "T - S" means that, provided that S is a
1219             // subset of T, it's the "set of all things in T but not in S". Things like "T | S"
1220             // mean the "union of T and S".
1221             
1222             // Is the child's type an object that isn't an other-object (i.e. object that could
1223             // have masquaredes-as-undefined traps) and isn't a function?  Then: we should fold
1224             // this to true.
1225             if (!(child.m_type & ~(SpecObject - SpecObjectOther - SpecFunction))) {
1226                 setConstant(node, jsBoolean(true));
1227                 constantWasSet = true;
1228                 break;
1229             }
1230             
1231             // Is the child's type definitely not either of: an object that isn't a function,
1232             // or either undefined or null?  Then: we should fold this to false.  This means
1233             // for example that if it's any non-function object, including those that have
1234             // masquerades-as-undefined traps, then we don't fold. It also means we won't fold
1235             // if it's undefined-or-null, since the type bits don't distinguish between
1236             // undefined (which should fold to false) and null (which should fold to true).
1237             if (!(child.m_type & ((SpecObject - SpecFunction) | SpecOther))) {
1238                 setConstant(node, jsBoolean(false));
1239                 constantWasSet = true;
1240                 break;
1241             }
1242             
1243             break;
1244         case IsFunction:
1245             if (!(child.m_type & ~SpecFunction)) {
1246                 setConstant(node, jsBoolean(true));
1247                 constantWasSet = true;
1248                 break;
1249             }
1250             
1251             if (!(child.m_type & (SpecFunction | SpecObjectOther | SpecProxyObject))) {
1252                 setConstant(node, jsBoolean(false));
1253                 constantWasSet = true;
1254                 break;
1255             }
1256             break;
1257
1258         case IsCellWithType:
1259             if (!(child.m_type & ~node->speculatedTypeForQuery())) {
1260                 setConstant(node, jsBoolean(true));
1261                 constantWasSet = true;
1262                 break;
1263             }
1264             if (!(child.m_type & node->speculatedTypeForQuery())) {
1265                 setConstant(node, jsBoolean(false));
1266                 constantWasSet = true;
1267                 break;
1268             }
1269             break;
1270
1271         case IsTypedArrayView:
1272             if (!(child.m_type & ~SpecTypedArrayView)) {
1273                 setConstant(node, jsBoolean(true));
1274                 constantWasSet = true;
1275                 break;
1276             }
1277             if (!(child.m_type & SpecTypedArrayView)) {
1278                 setConstant(node, jsBoolean(false));
1279                 constantWasSet = true;
1280                 break;
1281             }
1282             break;
1283
1284         default:
1285             break;
1286         }
1287         if (constantWasSet)
1288             break;
1289         
1290         forNode(node).setType(SpecBoolean);
1291         break;
1292     }
1293
1294     case TypeOf: {
1295         JSValue child = forNode(node->child1()).value();
1296         AbstractValue& abstractChild = forNode(node->child1());
1297         if (child) {
1298             JSValue typeString = jsTypeStringForValue(m_vm, m_codeBlock->globalObjectFor(node->origin.semantic), child);
1299             setConstant(node, *m_graph.freeze(typeString));
1300             break;
1301         }
1302         
1303         if (isFullNumberSpeculation(abstractChild.m_type)) {
1304             setConstant(node, *m_graph.freeze(m_vm.smallStrings.numberString()));
1305             break;
1306         }
1307         
1308         if (isStringSpeculation(abstractChild.m_type)) {
1309             setConstant(node, *m_graph.freeze(m_vm.smallStrings.stringString()));
1310             break;
1311         }
1312
1313         // FIXME: We could use the masquerades-as-undefined watchpoint here.
1314         // https://bugs.webkit.org/show_bug.cgi?id=144456
1315         if (!(abstractChild.m_type & ~(SpecObject - SpecObjectOther - SpecFunction))) {
1316             setConstant(node, *m_graph.freeze(m_vm.smallStrings.objectString()));
1317             break;
1318         }
1319         
1320         if (isFunctionSpeculation(abstractChild.m_type)) {
1321             setConstant(node, *m_graph.freeze(m_vm.smallStrings.functionString()));
1322             break;
1323         }
1324         
1325         if (isBooleanSpeculation(abstractChild.m_type)) {
1326             setConstant(node, *m_graph.freeze(m_vm.smallStrings.booleanString()));
1327             break;
1328         }
1329
1330         if (isSymbolSpeculation(abstractChild.m_type)) {
1331             setConstant(node, *m_graph.freeze(m_vm.smallStrings.symbolString()));
1332             break;
1333         }
1334
1335         forNode(node).setType(m_graph, SpecStringIdent);
1336         break;
1337     }
1338             
1339     case CompareLess:
1340     case CompareLessEq:
1341     case CompareGreater:
1342     case CompareGreaterEq:
1343     case CompareEq: {
1344         JSValue leftConst = forNode(node->child1()).value();
1345         JSValue rightConst = forNode(node->child2()).value();
1346         if (leftConst && rightConst) {
1347             if (leftConst.isNumber() && rightConst.isNumber()) {
1348                 double a = leftConst.asNumber();
1349                 double b = rightConst.asNumber();
1350                 switch (node->op()) {
1351                 case CompareLess:
1352                     setConstant(node, jsBoolean(a < b));
1353                     break;
1354                 case CompareLessEq:
1355                     setConstant(node, jsBoolean(a <= b));
1356                     break;
1357                 case CompareGreater:
1358                     setConstant(node, jsBoolean(a > b));
1359                     break;
1360                 case CompareGreaterEq:
1361                     setConstant(node, jsBoolean(a >= b));
1362                     break;
1363                 case CompareEq:
1364                     setConstant(node, jsBoolean(a == b));
1365                     break;
1366                 default:
1367                     RELEASE_ASSERT_NOT_REACHED();
1368                     break;
1369                 }
1370                 break;
1371             }
1372             
1373             if (leftConst.isString() && rightConst.isString()) {
1374                 const StringImpl* a = asString(leftConst)->tryGetValueImpl();
1375                 const StringImpl* b = asString(rightConst)->tryGetValueImpl();
1376                 if (a && b) {
1377                     bool result;
1378                     if (node->op() == CompareEq)
1379                         result = WTF::equal(a, b);
1380                     else if (node->op() == CompareLess)
1381                         result = codePointCompare(a, b) < 0;
1382                     else if (node->op() == CompareLessEq)
1383                         result = codePointCompare(a, b) <= 0;
1384                     else if (node->op() == CompareGreater)
1385                         result = codePointCompare(a, b) > 0;
1386                     else if (node->op() == CompareGreaterEq)
1387                         result = codePointCompare(a, b) >= 0;
1388                     else
1389                         RELEASE_ASSERT_NOT_REACHED();
1390                     setConstant(node, jsBoolean(result));
1391                     break;
1392                 }
1393             }
1394
1395             if (node->op() == CompareEq && leftConst.isSymbol() && rightConst.isSymbol()) {
1396                 setConstant(node, jsBoolean(asSymbol(leftConst) == asSymbol(rightConst)));
1397                 break;
1398             }
1399         }
1400         
1401         if (node->op() == CompareEq) {
1402             SpeculatedType leftType = forNode(node->child1()).m_type;
1403             SpeculatedType rightType = forNode(node->child2()).m_type;
1404             if (!valuesCouldBeEqual(leftType, rightType)) {
1405                 setConstant(node, jsBoolean(false));
1406                 break;
1407             }
1408
1409             if (leftType == SpecOther)
1410                 std::swap(leftType, rightType);
1411             if (rightType == SpecOther) {
1412                 // Undefined and Null are always equal when compared to eachother.
1413                 if (!(leftType & ~SpecOther)) {
1414                     setConstant(node, jsBoolean(true));
1415                     break;
1416                 }
1417
1418                 // Any other type compared to Null or Undefined is always false
1419                 // as long as the MasqueradesAsUndefined watchpoint is valid.
1420                 //
1421                 // MasqueradesAsUndefined only matters for SpecObjectOther, other
1422                 // cases are always "false".
1423                 if (!(leftType & (SpecObjectOther | SpecOther))) {
1424                     setConstant(node, jsBoolean(false));
1425                     break;
1426                 }
1427
1428                 if (!(leftType & SpecOther) && m_graph.masqueradesAsUndefinedWatchpointIsStillValid(node->origin.semantic)) {
1429                     JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
1430                     m_graph.watchpoints().addLazily(globalObject->masqueradesAsUndefinedWatchpoint());
1431                     setConstant(node, jsBoolean(false));
1432                     break;
1433                 }
1434             }
1435         }
1436         
1437         if (node->child1() == node->child2()) {
1438             if (node->isBinaryUseKind(Int32Use) ||
1439                 node->isBinaryUseKind(Int52RepUse) ||
1440                 node->isBinaryUseKind(StringUse) ||
1441                 node->isBinaryUseKind(BooleanUse) ||
1442                 node->isBinaryUseKind(SymbolUse) ||
1443                 node->isBinaryUseKind(StringIdentUse) ||
1444                 node->isBinaryUseKind(ObjectUse) ||
1445                 node->isBinaryUseKind(ObjectUse, ObjectOrOtherUse) ||
1446                 node->isBinaryUseKind(ObjectOrOtherUse, ObjectUse)) {
1447                 switch (node->op()) {
1448                 case CompareLess:
1449                 case CompareGreater:
1450                     setConstant(node, jsBoolean(false));
1451                     break;
1452                 case CompareLessEq:
1453                 case CompareGreaterEq:
1454                 case CompareEq:
1455                     setConstant(node, jsBoolean(true));
1456                     break;
1457                 default:
1458                     DFG_CRASH(m_graph, node, "Unexpected node type");
1459                     break;
1460                 }
1461                 break;
1462             }
1463         }
1464         
1465         forNode(node).setType(SpecBoolean);
1466         break;
1467     }
1468             
1469     case CompareStrictEq: {
1470         Node* leftNode = node->child1().node();
1471         Node* rightNode = node->child2().node();
1472         JSValue left = forNode(leftNode).value();
1473         JSValue right = forNode(rightNode).value();
1474         if (left && right) {
1475             if (left.isString() && right.isString()) {
1476                 // We need this case because JSValue::strictEqual is otherwise too racy for
1477                 // string comparisons.
1478                 const StringImpl* a = asString(left)->tryGetValueImpl();
1479                 const StringImpl* b = asString(right)->tryGetValueImpl();
1480                 if (a && b) {
1481                     setConstant(node, jsBoolean(WTF::equal(a, b)));
1482                     break;
1483                 }
1484             } else {
1485                 setConstant(node, jsBoolean(JSValue::strictEqual(0, left, right)));
1486                 break;
1487             }
1488         }
1489         
1490         SpeculatedType leftLUB = leastUpperBoundOfStrictlyEquivalentSpeculations(forNode(leftNode).m_type);
1491         SpeculatedType rightLUB = leastUpperBoundOfStrictlyEquivalentSpeculations(forNode(rightNode).m_type);
1492         if (!(leftLUB & rightLUB)) {
1493             setConstant(node, jsBoolean(false));
1494             break;
1495         }
1496         
1497         if (node->child1() == node->child2()) {
1498             if (node->isBinaryUseKind(BooleanUse) ||
1499                 node->isBinaryUseKind(Int32Use) ||
1500                 node->isBinaryUseKind(Int52RepUse) ||
1501                 node->isBinaryUseKind(StringUse) ||
1502                 node->isBinaryUseKind(StringIdentUse) ||
1503                 node->isBinaryUseKind(SymbolUse) ||
1504                 node->isBinaryUseKind(ObjectUse) ||
1505                 node->isBinaryUseKind(MiscUse, UntypedUse) ||
1506                 node->isBinaryUseKind(UntypedUse, MiscUse) ||
1507                 node->isBinaryUseKind(StringIdentUse, NotStringVarUse) ||
1508                 node->isBinaryUseKind(NotStringVarUse, StringIdentUse) ||
1509                 node->isBinaryUseKind(StringUse, UntypedUse) ||
1510                 node->isBinaryUseKind(UntypedUse, StringUse)) {
1511                 setConstant(node, jsBoolean(true));
1512                 break;
1513             }
1514         }
1515
1516         forNode(node).setType(SpecBoolean);
1517         break;
1518     }
1519         
1520     case CompareEqPtr: {
1521         Node* childNode = node->child1().node();
1522         JSValue childValue = forNode(childNode).value();
1523         if (childValue) {
1524             setConstant(node, jsBoolean(childValue.isCell() && childValue.asCell() == node->cellOperand()->cell()));
1525             break;
1526         }
1527         
1528         forNode(node).setType(SpecBoolean);
1529         break;
1530     }
1531         
1532     case StringCharCodeAt:
1533         forNode(node).setType(SpecInt32Only);
1534         break;
1535         
1536     case StringFromCharCode:
1537         forNode(node).setType(m_graph, SpecString);
1538         break;
1539
1540     case StringCharAt:
1541         forNode(node).set(m_graph, m_vm.stringStructure.get());
1542         break;
1543             
1544     case GetByVal:
1545     case AtomicsAdd:
1546     case AtomicsAnd:
1547     case AtomicsCompareExchange:
1548     case AtomicsExchange:
1549     case AtomicsLoad:
1550     case AtomicsOr:
1551     case AtomicsStore:
1552     case AtomicsSub:
1553     case AtomicsXor: {
1554         if (node->op() != GetByVal)
1555             clobberWorld(node->origin.semantic, clobberLimit);
1556         switch (node->arrayMode().type()) {
1557         case Array::SelectUsingPredictions:
1558         case Array::Unprofiled:
1559         case Array::SelectUsingArguments:
1560             RELEASE_ASSERT_NOT_REACHED();
1561             break;
1562         case Array::ForceExit:
1563             m_state.setIsValid(false);
1564             break;
1565         case Array::Undecided: {
1566             JSValue index = forNode(node->child2()).value();
1567             if (index && index.isInt32() && index.asInt32() >= 0) {
1568                 setConstant(node, jsUndefined());
1569                 break;
1570             }
1571             forNode(node).setType(SpecOther);
1572             break;
1573         }
1574         case Array::Generic:
1575             clobberWorld(node->origin.semantic, clobberLimit);
1576             forNode(node).makeHeapTop();
1577             break;
1578         case Array::String:
1579             if (node->arrayMode().isOutOfBounds()) {
1580                 // If the watchpoint was still valid we could totally set this to be
1581                 // SpecString | SpecOther. Except that we'd have to be careful. If we
1582                 // tested the watchpoint state here then it could change by the time
1583                 // we got to the backend. So to do this right, we'd have to get the
1584                 // fixup phase to check the watchpoint state and then bake into the
1585                 // GetByVal operation the fact that we're using a watchpoint, using
1586                 // something like Array::SaneChain (except not quite, because that
1587                 // implies an in-bounds access). None of this feels like it's worth it,
1588                 // so we're going with TOP for now. The same thing applies to
1589                 // clobbering the world.
1590                 clobberWorld(node->origin.semantic, clobberLimit);
1591                 forNode(node).makeHeapTop();
1592             } else
1593                 forNode(node).set(m_graph, m_vm.stringStructure.get());
1594             break;
1595         case Array::DirectArguments:
1596         case Array::ScopedArguments:
1597             forNode(node).makeHeapTop();
1598             break;
1599         case Array::Int32:
1600             if (node->arrayMode().isOutOfBounds()) {
1601                 clobberWorld(node->origin.semantic, clobberLimit);
1602                 forNode(node).makeHeapTop();
1603             } else
1604                 forNode(node).setType(SpecInt32Only);
1605             break;
1606         case Array::Double:
1607             if (node->arrayMode().isOutOfBounds()) {
1608                 clobberWorld(node->origin.semantic, clobberLimit);
1609                 forNode(node).makeHeapTop();
1610             } else if (node->arrayMode().isSaneChain())
1611                 forNode(node).setType(SpecBytecodeDouble);
1612             else
1613                 forNode(node).setType(SpecDoubleReal);
1614             break;
1615         case Array::Contiguous:
1616         case Array::ArrayStorage:
1617         case Array::SlowPutArrayStorage:
1618             if (node->arrayMode().isOutOfBounds())
1619                 clobberWorld(node->origin.semantic, clobberLimit);
1620             forNode(node).makeHeapTop();
1621             break;
1622         case Array::Int8Array:
1623             forNode(node).setType(SpecInt32Only);
1624             break;
1625         case Array::Int16Array:
1626             forNode(node).setType(SpecInt32Only);
1627             break;
1628         case Array::Int32Array:
1629             forNode(node).setType(SpecInt32Only);
1630             break;
1631         case Array::Uint8Array:
1632             forNode(node).setType(SpecInt32Only);
1633             break;
1634         case Array::Uint8ClampedArray:
1635             forNode(node).setType(SpecInt32Only);
1636             break;
1637         case Array::Uint16Array:
1638             forNode(node).setType(SpecInt32Only);
1639             break;
1640         case Array::Uint32Array:
1641             if (node->shouldSpeculateInt32())
1642                 forNode(node).setType(SpecInt32Only);
1643             else if (enableInt52() && node->shouldSpeculateAnyInt())
1644                 forNode(node).setType(SpecAnyInt);
1645             else
1646                 forNode(node).setType(SpecAnyIntAsDouble);
1647             break;
1648         case Array::Float32Array:
1649             forNode(node).setType(SpecFullDouble);
1650             break;
1651         case Array::Float64Array:
1652             forNode(node).setType(SpecFullDouble);
1653             break;
1654         default:
1655             RELEASE_ASSERT_NOT_REACHED();
1656             break;
1657         }
1658         break;
1659     }
1660             
1661     case PutByValDirect:
1662     case PutByVal:
1663     case PutByValAlias: {
1664         switch (node->arrayMode().modeForPut().type()) {
1665         case Array::ForceExit:
1666             m_state.setIsValid(false);
1667             break;
1668         case Array::Generic:
1669             clobberWorld(node->origin.semantic, clobberLimit);
1670             break;
1671         case Array::Int32:
1672             if (node->arrayMode().isOutOfBounds())
1673                 clobberWorld(node->origin.semantic, clobberLimit);
1674             break;
1675         case Array::Double:
1676             if (node->arrayMode().isOutOfBounds())
1677                 clobberWorld(node->origin.semantic, clobberLimit);
1678             break;
1679         case Array::Contiguous:
1680         case Array::ArrayStorage:
1681             if (node->arrayMode().isOutOfBounds())
1682                 clobberWorld(node->origin.semantic, clobberLimit);
1683             break;
1684         case Array::SlowPutArrayStorage:
1685             if (node->arrayMode().mayStoreToHole())
1686                 clobberWorld(node->origin.semantic, clobberLimit);
1687             break;
1688         default:
1689             break;
1690         }
1691         break;
1692     }
1693             
1694     case ArrayPush:
1695         clobberWorld(node->origin.semantic, clobberLimit);
1696         forNode(node).setType(SpecBytecodeNumber);
1697         break;
1698
1699     case ArraySlice: {
1700         JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
1701
1702         // FIXME: We could do better here if we prove that the
1703         // incoming value has only a single structure.
1704         RegisteredStructureSet structureSet;
1705         structureSet.add(m_graph.registerStructure(globalObject->originalArrayStructureForIndexingType(ArrayWithInt32)));
1706         structureSet.add(m_graph.registerStructure(globalObject->originalArrayStructureForIndexingType(ArrayWithContiguous)));
1707         structureSet.add(m_graph.registerStructure(globalObject->originalArrayStructureForIndexingType(ArrayWithDouble)));
1708
1709         forNode(node).set(m_graph, structureSet);
1710         break;
1711     }
1712
1713     case ArrayIndexOf: {
1714         forNode(node).setType(SpecInt32Only);
1715         break;
1716     }
1717             
1718     case ArrayPop:
1719         clobberWorld(node->origin.semantic, clobberLimit);
1720         forNode(node).makeHeapTop();
1721         break;
1722         
1723     case GetMyArgumentByVal:
1724     case GetMyArgumentByValOutOfBounds: {
1725         JSValue index = forNode(node->child2()).m_value;
1726         InlineCallFrame* inlineCallFrame = node->child1()->origin.semantic.inlineCallFrame;
1727
1728         if (index && index.isInt32()) {
1729             // This pretends to return TOP for accesses that are actually proven out-of-bounds because
1730             // that's the conservative thing to do. Otherwise we'd need to write more code to mark such
1731             // paths as unreachable, or to return undefined. We could implement that eventually.
1732             
1733             unsigned argumentIndex = index.asUInt32() + node->numberOfArgumentsToSkip();
1734             if (inlineCallFrame) {
1735                 if (argumentIndex < inlineCallFrame->arguments.size() - 1) {
1736                     forNode(node) = m_state.variables().operand(
1737                         virtualRegisterForArgument(argumentIndex + 1) + inlineCallFrame->stackOffset);
1738                     m_state.setFoundConstants(true);
1739                     break;
1740                 }
1741             } else {
1742                 if (argumentIndex < m_state.variables().numberOfArguments() - 1) {
1743                     forNode(node) = m_state.variables().argument(argumentIndex + 1);
1744                     m_state.setFoundConstants(true);
1745                     break;
1746                 }
1747             }
1748         }
1749         
1750         if (inlineCallFrame) {
1751             // We have a bound on the types even though it's random access. Take advantage of this.
1752             
1753             AbstractValue result;
1754             for (unsigned i = 1 + node->numberOfArgumentsToSkip(); i < inlineCallFrame->arguments.size(); ++i) {
1755                 result.merge(
1756                     m_state.variables().operand(
1757                         virtualRegisterForArgument(i) + inlineCallFrame->stackOffset));
1758             }
1759             
1760             if (node->op() == GetMyArgumentByValOutOfBounds)
1761                 result.merge(SpecOther);
1762             
1763             if (result.value())
1764                 m_state.setFoundConstants(true);
1765             
1766             forNode(node) = result;
1767             break;
1768         }
1769         
1770         forNode(node).makeHeapTop();
1771         break;
1772     }
1773             
1774     case RegExpExec:
1775         if (node->child2().useKind() == RegExpObjectUse
1776             && node->child3().useKind() == StringUse) {
1777             // This doesn't clobber the world since there are no conversions to perform.
1778         } else
1779             clobberWorld(node->origin.semantic, clobberLimit);
1780         if (JSValue globalObjectValue = forNode(node->child1()).m_value) {
1781             if (JSGlobalObject* globalObject = jsDynamicCast<JSGlobalObject*>(m_vm, globalObjectValue)) {
1782                 if (!globalObject->isHavingABadTime()) {
1783                     m_graph.watchpoints().addLazily(globalObject->havingABadTimeWatchpoint());
1784                     Structure* structure = globalObject->regExpMatchesArrayStructure();
1785                     m_graph.registerStructure(structure);
1786                     forNode(node).set(m_graph, structure);
1787                     forNode(node).merge(SpecOther);
1788                     break;
1789                 }
1790             }
1791         }
1792         forNode(node).setType(m_graph, SpecOther | SpecArray);
1793         break;
1794
1795     case RegExpTest:
1796         if (node->child2().useKind() == RegExpObjectUse
1797             && node->child3().useKind() == StringUse) {
1798             // This doesn't clobber the world since there are no conversions to perform.
1799         } else
1800             clobberWorld(node->origin.semantic, clobberLimit);
1801         forNode(node).setType(SpecBoolean);
1802         break;
1803             
1804     case StringReplace:
1805     case StringReplaceRegExp:
1806         if (node->child1().useKind() == StringUse
1807             && node->child2().useKind() == RegExpObjectUse
1808             && node->child3().useKind() == StringUse) {
1809             // This doesn't clobber the world. It just reads and writes regexp state.
1810         } else
1811             clobberWorld(node->origin.semantic, clobberLimit);
1812         forNode(node).set(m_graph, m_vm.stringStructure.get());
1813         break;
1814
1815     case Jump:
1816         break;
1817             
1818     case Branch: {
1819         Node* child = node->child1().node();
1820         BooleanResult result = booleanResult(node, forNode(child));
1821         if (result == DefinitelyTrue) {
1822             m_state.setBranchDirection(TakeTrue);
1823             break;
1824         }
1825         if (result == DefinitelyFalse) {
1826             m_state.setBranchDirection(TakeFalse);
1827             break;
1828         }
1829         // FIXME: The above handles the trivial cases of sparse conditional
1830         // constant propagation, but we can do better:
1831         // We can specialize the source variable's value on each direction of
1832         // the branch.
1833         m_state.setBranchDirection(TakeBoth);
1834         break;
1835     }
1836         
1837     case Switch: {
1838         // Nothing to do for now.
1839         // FIXME: Do sparse conditional things.
1840         break;
1841     }
1842             
1843     case Return:
1844         m_state.setIsValid(false);
1845         break;
1846
1847     case TailCall:
1848     case DirectTailCall:
1849     case TailCallVarargs:
1850     case TailCallForwardVarargs:
1851         clobberWorld(node->origin.semantic, clobberLimit);
1852         m_state.setIsValid(false);
1853         break;
1854         
1855     case Throw:
1856     case ThrowStaticError:
1857         m_state.setIsValid(false);
1858         break;
1859             
1860     case ToPrimitive: {
1861         JSValue childConst = forNode(node->child1()).value();
1862         if (childConst && childConst.isNumber()) {
1863             setConstant(node, childConst);
1864             break;
1865         }
1866         
1867         ASSERT(node->child1().useKind() == UntypedUse);
1868         
1869         if (!(forNode(node->child1()).m_type & ~(SpecFullNumber | SpecBoolean | SpecString | SpecSymbol))) {
1870             m_state.setFoundConstants(true);
1871             forNode(node) = forNode(node->child1());
1872             break;
1873         }
1874         
1875         clobberWorld(node->origin.semantic, clobberLimit);
1876         
1877         forNode(node).setType(m_graph, SpecHeapTop & ~SpecObject);
1878         break;
1879     }
1880
1881     case ToNumber: {
1882         JSValue childConst = forNode(node->child1()).value();
1883         if (childConst && childConst.isNumber()) {
1884             setConstant(node, childConst);
1885             break;
1886         }
1887
1888         ASSERT(node->child1().useKind() == UntypedUse);
1889
1890         if (!(forNode(node->child1()).m_type & ~SpecBytecodeNumber)) {
1891             m_state.setFoundConstants(true);
1892             forNode(node) = forNode(node->child1());
1893             break;
1894         }
1895
1896         clobberWorld(node->origin.semantic, clobberLimit);
1897         forNode(node).setType(m_graph, SpecBytecodeNumber);
1898         break;
1899     }
1900         
1901     case ToString:
1902     case CallStringConstructor: {
1903         switch (node->child1().useKind()) {
1904         case StringObjectUse:
1905             // This also filters that the StringObject has the primordial StringObject
1906             // structure.
1907             filter(
1908                 node->child1(),
1909                 m_graph.registerStructure(m_graph.globalObjectFor(node->origin.semantic)->stringObjectStructure()));
1910             break;
1911         case StringOrStringObjectUse:
1912         case Int32Use:
1913         case Int52RepUse:
1914         case DoubleRepUse:
1915         case NotCellUse:
1916             break;
1917         case CellUse:
1918         case UntypedUse:
1919             clobberWorld(node->origin.semantic, clobberLimit);
1920             break;
1921         default:
1922             RELEASE_ASSERT_NOT_REACHED();
1923             break;
1924         }
1925         forNode(node).set(m_graph, m_vm.stringStructure.get());
1926         break;
1927     }
1928
1929     case NumberToStringWithRadix:
1930         clobberWorld(node->origin.semantic, clobberLimit);
1931         forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
1932         break;
1933         
1934     case NewStringObject: {
1935         ASSERT(node->structure()->classInfo() == StringObject::info());
1936         forNode(node).set(m_graph, node->structure());
1937         break;
1938     }
1939             
1940     case NewArray:
1941         forNode(node).set(
1942             m_graph,
1943             m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()));
1944         break;
1945
1946     case NewArrayWithSpread:
1947         if (m_graph.isWatchingHavingABadTimeWatchpoint(node)) {
1948             // We've compiled assuming we're not having a bad time, so to be consistent
1949             // with StructureRegisterationPhase we must say we produce an original array
1950             // allocation structure.
1951             forNode(node).set(
1952                 m_graph,
1953                 m_graph.globalObjectFor(node->origin.semantic)->originalArrayStructureForIndexingType(ArrayWithContiguous));
1954         } else {
1955             forNode(node).set(
1956                 m_graph,
1957                 m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous));
1958         }
1959
1960         break;
1961
1962     case Spread:
1963         forNode(node).set(
1964             m_graph, m_vm.fixedArrayStructure.get());
1965         break;
1966         
1967     case NewArrayBuffer:
1968         forNode(node).set(
1969             m_graph,
1970             m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()));
1971         break;
1972
1973     case NewArrayWithSize:
1974         forNode(node).setType(m_graph, SpecArray);
1975         break;
1976         
1977     case NewTypedArray:
1978         switch (node->child1().useKind()) {
1979         case Int32Use:
1980             break;
1981         case UntypedUse:
1982             clobberWorld(node->origin.semantic, clobberLimit);
1983             break;
1984         default:
1985             RELEASE_ASSERT_NOT_REACHED();
1986             break;
1987         }
1988         forNode(node).set(
1989             m_graph,
1990             m_graph.globalObjectFor(node->origin.semantic)->typedArrayStructureConcurrently(
1991                 node->typedArrayType()));
1992         break;
1993         
1994     case NewRegexp:
1995         forNode(node).set(m_graph, m_graph.globalObjectFor(node->origin.semantic)->regExpStructure());
1996         break;
1997             
1998     case ToThis: {
1999         AbstractValue& source = forNode(node->child1());
2000         AbstractValue& destination = forNode(node);
2001         bool strictMode = m_graph.executableFor(node->origin.semantic)->isStrictMode();
2002
2003         if (isToThisAnIdentity(strictMode, source)) {
2004             m_state.setFoundConstants(true);
2005             destination = source;
2006             break;
2007         }
2008
2009         if (strictMode)
2010             destination.makeHeapTop();
2011         else {
2012             destination = source;
2013             destination.merge(SpecObject);
2014         }
2015         break;
2016     }
2017
2018     case CreateThis: {
2019         // FIXME: We can fold this to NewObject if the incoming callee is a constant.
2020         forNode(node).setType(m_graph, SpecFinalObject);
2021         break;
2022     }
2023         
2024     case NewObject:
2025         ASSERT(!!node->structure().get());
2026         forNode(node).set(m_graph, node->structure());
2027         break;
2028
2029     case CallObjectConstructor: {
2030         AbstractValue& source = forNode(node->child1());
2031         AbstractValue& destination = forNode(node);
2032
2033         if (!(source.m_type & ~SpecObject)) {
2034             m_state.setFoundConstants(true);
2035             destination = source;
2036             break;
2037         }
2038
2039         forNode(node).setType(m_graph, SpecObject);
2040         break;
2041     }
2042
2043     case PhantomNewObject:
2044     case PhantomNewFunction:
2045     case PhantomNewGeneratorFunction:
2046     case PhantomNewAsyncFunction:
2047     case PhantomCreateActivation:
2048     case PhantomDirectArguments:
2049     case PhantomClonedArguments:
2050     case PhantomCreateRest:
2051     case PhantomSpread:
2052     case PhantomNewArrayWithSpread:
2053     case BottomValue:
2054         m_state.setDidClobber(true); // Prevent constant folding.
2055         // This claims to return bottom.
2056         break;
2057         
2058     case PutHint:
2059         break;
2060         
2061     case MaterializeNewObject: {
2062         forNode(node).set(m_graph, node->structureSet());
2063         break;
2064     }
2065
2066     case PushWithScope:
2067         clobberWorld(node->origin.semantic, clobberLimit);
2068
2069         // We don't use the more precise withScopeStructure() here because it is a LazyProperty and may not yet be allocated.
2070         forNode(node).setType(m_graph, SpecObjectOther);
2071         break;
2072
2073     case CreateActivation:
2074     case MaterializeCreateActivation:
2075         forNode(node).set(
2076             m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->activationStructure());
2077         break;
2078         
2079     case CreateDirectArguments:
2080         forNode(node).set(m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->directArgumentsStructure());
2081         break;
2082         
2083     case CreateScopedArguments:
2084         forNode(node).set(m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->scopedArgumentsStructure());
2085         break;
2086         
2087     case CreateClonedArguments:
2088         if (!m_graph.isWatchingHavingABadTimeWatchpoint(node)) {
2089             forNode(node).setType(m_graph, SpecObject);
2090             break;
2091         }
2092         forNode(node).set(m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->clonedArgumentsStructure());
2093         break;
2094
2095     case NewGeneratorFunction:
2096         forNode(node).set(
2097             m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->generatorFunctionStructure());
2098         break;
2099
2100     case NewAsyncFunction:
2101         forNode(node).set(
2102             m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->asyncFunctionStructure());
2103         break;
2104
2105     case NewFunction:
2106         forNode(node).set(
2107             m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->functionStructure());
2108         break;
2109         
2110     case GetCallee:
2111         if (FunctionExecutable* executable = jsDynamicCast<FunctionExecutable*>(m_vm, m_codeBlock->ownerExecutable())) {
2112             InferredValue* singleton = executable->singletonFunction();
2113             if (JSValue value = singleton->inferredValue()) {
2114                 m_graph.watchpoints().addLazily(singleton);
2115                 JSFunction* function = jsCast<JSFunction*>(value);
2116                 setConstant(node, *m_graph.freeze(function));
2117                 break;
2118             }
2119         }
2120         forNode(node).setType(m_graph, SpecFunction);
2121         break;
2122         
2123     case GetArgumentCountIncludingThis:
2124         forNode(node).setType(SpecInt32Only);
2125         break;
2126         
2127     case GetRestLength:
2128         forNode(node).setType(SpecInt32Only);
2129         break;
2130         
2131     case GetGetter: {
2132         JSValue base = forNode(node->child1()).m_value;
2133         if (base) {
2134             GetterSetter* getterSetter = jsCast<GetterSetter*>(base);
2135             if (!getterSetter->isGetterNull()) {
2136                 setConstant(node, *m_graph.freeze(getterSetter->getterConcurrently()));
2137                 break;
2138             }
2139         }
2140         
2141         forNode(node).setType(m_graph, SpecObject);
2142         break;
2143     }
2144         
2145     case GetSetter: {
2146         JSValue base = forNode(node->child1()).m_value;
2147         if (base) {
2148             GetterSetter* getterSetter = jsCast<GetterSetter*>(base);
2149             if (!getterSetter->isSetterNull()) {
2150                 setConstant(node, *m_graph.freeze(getterSetter->setterConcurrently()));
2151                 break;
2152             }
2153         }
2154         
2155         forNode(node).setType(m_graph, SpecObject);
2156         break;
2157     }
2158         
2159     case GetScope:
2160         if (JSValue base = forNode(node->child1()).m_value) {
2161             if (JSFunction* function = jsDynamicCast<JSFunction*>(m_vm, base)) {
2162                 setConstant(node, *m_graph.freeze(function->scope()));
2163                 break;
2164             }
2165         }
2166         forNode(node).setType(m_graph, SpecObjectOther);
2167         break;
2168
2169     case SkipScope: {
2170         JSValue child = forNode(node->child1()).value();
2171         if (child) {
2172             setConstant(node, *m_graph.freeze(JSValue(jsCast<JSScope*>(child.asCell())->next())));
2173             break;
2174         }
2175         forNode(node).setType(m_graph, SpecObjectOther);
2176         break;
2177     }
2178
2179     case GetGlobalObject: {
2180         JSValue child = forNode(node->child1()).value();
2181         if (child) {
2182             setConstant(node, *m_graph.freeze(JSValue(asObject(child)->globalObject())));
2183             break;
2184         }
2185
2186         if (forNode(node->child1()).m_structure.isFinite()) {
2187             JSGlobalObject* globalObject = nullptr;
2188             bool ok = true;
2189             forNode(node->child1()).m_structure.forEach(
2190                 [&] (RegisteredStructure structure) {
2191                     if (!globalObject)
2192                         globalObject = structure->globalObject();
2193                     else if (globalObject != structure->globalObject())
2194                         ok = false;
2195                 });
2196             if (globalObject && ok) {
2197                 setConstant(node, *m_graph.freeze(JSValue(globalObject)));
2198                 break;
2199             }
2200         }
2201
2202         forNode(node).setType(m_graph, SpecObjectOther);
2203         break;
2204     }
2205
2206     case GetClosureVar:
2207         if (JSValue value = m_graph.tryGetConstantClosureVar(forNode(node->child1()), node->scopeOffset())) {
2208             setConstant(node, *m_graph.freeze(value));
2209             break;
2210         }
2211         forNode(node).makeBytecodeTop();
2212         break;
2213             
2214     case PutClosureVar:
2215         break;
2216
2217     case GetRegExpObjectLastIndex:
2218         forNode(node).makeHeapTop();
2219         break;
2220
2221     case SetRegExpObjectLastIndex:
2222     case RecordRegExpCachedResult:
2223         break;
2224         
2225     case GetFromArguments:
2226         forNode(node).makeHeapTop();
2227         break;
2228         
2229     case PutToArguments:
2230         break;
2231
2232     case GetArgument:
2233         forNode(node).makeHeapTop();
2234         break;
2235
2236     case TryGetById:
2237         // FIXME: This should constant fold at least as well as the normal GetById case.
2238         // https://bugs.webkit.org/show_bug.cgi?id=156422
2239         forNode(node).makeHeapTop();
2240         break;
2241
2242     case GetById:
2243     case GetByIdFlush: {
2244         if (!node->prediction()) {
2245             m_state.setIsValid(false);
2246             break;
2247         }
2248         
2249         AbstractValue& value = forNode(node->child1());
2250         if (value.m_structure.isFinite()
2251             && (node->child1().useKind() == CellUse || !(value.m_type & ~SpecCell))) {
2252             UniquedStringImpl* uid = m_graph.identifiers()[node->identifierNumber()];
2253             GetByIdStatus status = GetByIdStatus::computeFor(value.m_structure.toStructureSet(), uid);
2254             if (status.isSimple()) {
2255                 // Figure out what the result is going to be - is it TOP, a constant, or maybe
2256                 // something more subtle?
2257                 AbstractValue result;
2258                 for (unsigned i = status.numVariants(); i--;) {
2259                     // This thing won't give us a variant that involves prototypes. If it did, we'd
2260                     // have more work to do here.
2261                     DFG_ASSERT(m_graph, node, status[i].conditionSet().isEmpty());
2262
2263                     result.merge(
2264                         m_graph.inferredValueForProperty(
2265                             value, uid, status[i].offset(), m_state.structureClobberState()));
2266                 }
2267                 m_state.setFoundConstants(true);
2268                 forNode(node) = result;
2269                 break;
2270             }
2271         }
2272
2273         clobberWorld(node->origin.semantic, clobberLimit);
2274         forNode(node).makeHeapTop();
2275         break;
2276     }
2277
2278     case GetByValWithThis:
2279     case GetByIdWithThis:
2280         clobberWorld(node->origin.semantic, clobberLimit);
2281         forNode(node).makeHeapTop();
2282         break;
2283             
2284     case GetArrayLength: {
2285         JSArrayBufferView* view = m_graph.tryGetFoldableView(
2286             forNode(node->child1()).m_value, node->arrayMode());
2287         if (view) {
2288             setConstant(node, jsNumber(view->length()));
2289             break;
2290         }
2291         forNode(node).setType(SpecInt32Only);
2292         break;
2293     }
2294
2295     case GetVectorLength: {
2296         forNode(node).setType(SpecInt32Only);
2297         break;
2298     }
2299
2300     case DeleteById:
2301     case DeleteByVal: {
2302         // FIXME: This could decide if the delete will be successful based on the set of structures that
2303         // we get from our base value. https://bugs.webkit.org/show_bug.cgi?id=156611
2304         clobberWorld(node->origin.semantic, clobberLimit);
2305         forNode(node).setType(SpecBoolean);
2306         break;
2307     }
2308         
2309     case CheckStructure: {
2310         AbstractValue& value = forNode(node->child1());
2311
2312         const RegisteredStructureSet& set = node->structureSet();
2313         
2314         // It's interesting that we could have proven that the object has a larger structure set
2315         // that includes the set we're testing. In that case we could make the structure check
2316         // more efficient. We currently don't.
2317         
2318         if (value.m_structure.isSubsetOf(set))
2319             m_state.setFoundConstants(true);
2320
2321         SpeculatedType admittedTypes = SpecNone;
2322         switch (node->child1().useKind()) {
2323         case CellUse:
2324         case KnownCellUse:
2325             admittedTypes = SpecNone;
2326             break;
2327         case CellOrOtherUse:
2328             admittedTypes = SpecOther;
2329             break;
2330         default:
2331             DFG_CRASH(m_graph, node, "Bad use kind");
2332             break;
2333         }
2334         
2335         filter(value, set, admittedTypes);
2336         break;
2337     }
2338         
2339     case CheckStructureImmediate: {
2340         // FIXME: This currently can only reason about one structure at a time.
2341         // https://bugs.webkit.org/show_bug.cgi?id=136988
2342         
2343         AbstractValue& value = forNode(node->child1());
2344         const RegisteredStructureSet& set = node->structureSet();
2345         
2346         if (value.value()) {
2347             if (Structure* structure = jsDynamicCast<Structure*>(m_vm, value.value())) {
2348                 if (set.contains(m_graph.registerStructure(structure))) {
2349                     m_state.setFoundConstants(true);
2350                     break;
2351                 }
2352             }
2353             m_state.setIsValid(false);
2354             break;
2355         }
2356         
2357         if (m_phiChildren) {
2358             bool allGood = true;
2359             m_phiChildren->forAllTransitiveIncomingValues(
2360                 node,
2361                 [&] (Node* incoming) {
2362                     if (Structure* structure = incoming->dynamicCastConstant<Structure*>(m_vm)) {
2363                         if (set.contains(m_graph.registerStructure(structure)))
2364                             return;
2365                     }
2366                     allGood = false;
2367                 });
2368             if (allGood) {
2369                 m_state.setFoundConstants(true);
2370                 break;
2371             }
2372         }
2373             
2374         if (RegisteredStructure structure = set.onlyStructure()) {
2375             filterByValue(node->child1(), *m_graph.freeze(structure.get()));
2376             break;
2377         }
2378         
2379         // Aw shucks, we can't do anything!
2380         break;
2381     }
2382         
2383     case PutStructure:
2384         if (!forNode(node->child1()).m_structure.isClear()) {
2385             if (forNode(node->child1()).m_structure.onlyStructure() == node->transition()->next)
2386                 m_state.setFoundConstants(true);
2387             else {
2388                 observeTransition(
2389                     clobberLimit, node->transition()->previous, node->transition()->next);
2390                 forNode(node->child1()).changeStructure(m_graph, node->transition()->next);
2391             }
2392         }
2393         break;
2394     case GetButterfly:
2395     case GetButterflyWithoutCaging:
2396     case AllocatePropertyStorage:
2397     case ReallocatePropertyStorage:
2398     case NukeStructureAndSetButterfly:
2399         // FIXME: We don't model the fact that the structureID is nuked, simply because currently
2400         // nobody would currently benefit from having that information. But it's a bug nonetheless.
2401         forNode(node).clear(); // The result is not a JS value.
2402         break;
2403     case CheckSubClass: {
2404         JSValue constant = forNode(node->child1()).value();
2405         if (constant) {
2406             if (constant.isCell() && constant.asCell()->inherits(m_vm, node->classInfo())) {
2407                 m_state.setFoundConstants(true);
2408                 ASSERT(constant);
2409                 break;
2410             }
2411         }
2412
2413         AbstractValue& value = forNode(node->child1());
2414
2415         if (value.m_structure.isSubClassOf(node->classInfo()))
2416             m_state.setFoundConstants(true);
2417
2418         filterClassInfo(value, node->classInfo());
2419         break;
2420     }
2421     case CallDOMGetter: {
2422         CallDOMGetterData* callDOMGetterData = node->callDOMGetterData();
2423         DOMJIT::CallDOMGetterSnippet* snippet = callDOMGetterData->snippet;
2424         if (!snippet || snippet->effect.writes)
2425             clobberWorld(node->origin.semantic, clobberLimit);
2426         if (callDOMGetterData->domJIT)
2427             forNode(node).setType(m_graph, callDOMGetterData->domJIT->resultType());
2428         else
2429             forNode(node).makeBytecodeTop();
2430         break;
2431     }
2432     case CallDOM: {
2433         const DOMJIT::Signature* signature = node->signature();
2434         if (signature->effect.writes)
2435             clobberWorld(node->origin.semantic, clobberLimit);
2436         forNode(node).setType(m_graph, signature->result);
2437         break;
2438     }
2439     case CheckArray: {
2440         if (node->arrayMode().alreadyChecked(m_graph, node, forNode(node->child1()))) {
2441             m_state.setFoundConstants(true);
2442             break;
2443         }
2444         switch (node->arrayMode().type()) {
2445         case Array::String:
2446             filter(node->child1(), SpecString);
2447             break;
2448         case Array::Int32:
2449         case Array::Double:
2450         case Array::Contiguous:
2451         case Array::Undecided:
2452         case Array::ArrayStorage:
2453         case Array::SlowPutArrayStorage:
2454             break;
2455         case Array::DirectArguments:
2456             filter(node->child1(), SpecDirectArguments);
2457             break;
2458         case Array::ScopedArguments:
2459             filter(node->child1(), SpecScopedArguments);
2460             break;
2461         case Array::Int8Array:
2462             filter(node->child1(), SpecInt8Array);
2463             break;
2464         case Array::Int16Array:
2465             filter(node->child1(), SpecInt16Array);
2466             break;
2467         case Array::Int32Array:
2468             filter(node->child1(), SpecInt32Array);
2469             break;
2470         case Array::Uint8Array:
2471             filter(node->child1(), SpecUint8Array);
2472             break;
2473         case Array::Uint8ClampedArray:
2474             filter(node->child1(), SpecUint8ClampedArray);
2475             break;
2476         case Array::Uint16Array:
2477             filter(node->child1(), SpecUint16Array);
2478             break;
2479         case Array::Uint32Array:
2480             filter(node->child1(), SpecUint32Array);
2481             break;
2482         case Array::Float32Array:
2483             filter(node->child1(), SpecFloat32Array);
2484             break;
2485         case Array::Float64Array:
2486             filter(node->child1(), SpecFloat64Array);
2487             break;
2488         case Array::AnyTypedArray:
2489             filter(node->child1(), SpecTypedArrayView);
2490             break;
2491         default:
2492             RELEASE_ASSERT_NOT_REACHED();
2493             break;
2494         }
2495         filterArrayModes(node->child1(), node->arrayMode().arrayModesThatPassFiltering());
2496         break;
2497     }
2498     case Arrayify: {
2499         if (node->arrayMode().alreadyChecked(m_graph, node, forNode(node->child1()))) {
2500             m_state.setFoundConstants(true);
2501             break;
2502         }
2503         ASSERT(node->arrayMode().conversion() == Array::Convert);
2504         clobberStructures(clobberLimit);
2505         filterArrayModes(node->child1(), node->arrayMode().arrayModesThatPassFiltering());
2506         break;
2507     }
2508     case ArrayifyToStructure: {
2509         AbstractValue& value = forNode(node->child1());
2510         if (value.m_structure.isSubsetOf(RegisteredStructureSet(node->structure())))
2511             m_state.setFoundConstants(true);
2512         clobberStructures(clobberLimit);
2513         
2514         // We have a bunch of options of how to express the abstract set at this point. Let set S
2515         // be the set of structures that the value had before clobbering and assume that all of
2516         // them are watchable. The new value should be the least expressible upper bound of the
2517         // intersection of "values that currently have structure = node->structure()" and "values
2518         // that have structure in S plus any structure transition-reachable from S". Assume that
2519         // node->structure() is not in S but it is transition-reachable from S. Then we would
2520         // like to say that the result is "values that have structure = node->structure() until
2521         // we invalidate", but there is no way to express this using the AbstractValue syntax. So
2522         // we must choose between:
2523         //
2524         // 1) "values that currently have structure = node->structure()". This is a valid
2525         //    superset of the value that we really want, and it's specific enough to satisfy the
2526         //    preconditions of the array access that this is guarding. It's also specific enough
2527         //    to allow relevant optimizations in the case that we didn't have a contradiction
2528         //    like in this example. Notice that in the abscence of any contradiction, this result
2529         //    is precise rather than being a conservative LUB.
2530         //
2531         // 2) "values that currently hava structure in S plus any structure transition-reachable
2532         //    from S". This is also a valid superset of the value that we really want, but it's
2533         //    not specific enough to satisfy the preconditions of the array access that this is
2534         //    guarding - so playing such shenanigans would preclude us from having assertions on
2535         //    the typing preconditions of any array accesses. This would also not be a desirable
2536         //    answer in the absence of a contradiction.
2537         //
2538         // Note that it's tempting to simply say that the resulting value is BOTTOM because of
2539         // the contradiction. That would be wrong, since we haven't hit an invalidation point,
2540         // yet.
2541         value.set(m_graph, node->structure());
2542         break;
2543     }
2544     case GetIndexedPropertyStorage: {
2545         JSArrayBufferView* view = m_graph.tryGetFoldableView(
2546             forNode(node->child1()).m_value, node->arrayMode());
2547         if (view)
2548             m_state.setFoundConstants(true);
2549         forNode(node).clear();
2550         break;
2551     }
2552     case ConstantStoragePointer: {
2553         forNode(node).clear();
2554         break; 
2555     }
2556         
2557     case GetTypedArrayByteOffset: {
2558         JSArrayBufferView* view = m_graph.tryGetFoldableView(forNode(node->child1()).m_value);
2559         if (view) {
2560             setConstant(node, jsNumber(view->byteOffset()));
2561             break;
2562         }
2563         forNode(node).setType(SpecInt32Only);
2564         break;
2565     }
2566         
2567     case GetByOffset: {
2568         StorageAccessData& data = node->storageAccessData();
2569         UniquedStringImpl* uid = m_graph.identifiers()[data.identifierNumber];
2570
2571         // FIXME: The part of this that handles inferred property types relies on AI knowing the structure
2572         // right now. That's probably not optimal. In some cases, we may perform an optimization (usually
2573         // by something other than AI, maybe by CSE for example) that obscures AI's view of the structure
2574         // at the point where GetByOffset runs. Currently, when that happens, we'll have to rely entirely
2575         // on the type that ByteCodeParser was able to prove.
2576         AbstractValue value = m_graph.inferredValueForProperty(
2577             forNode(node->child2()), uid, data.offset, m_state.structureClobberState());
2578
2579         // It's possible that the type that ByteCodeParser came up with is better.
2580         AbstractValue typeFromParsing;
2581         typeFromParsing.set(m_graph, data.inferredType, m_state.structureClobberState());
2582         value.filter(typeFromParsing);
2583
2584         // If we decide that there does not exist any value that this can return, then it's probably
2585         // because the compilation was already invalidated.
2586         if (value.isClear())
2587             m_state.setIsValid(false);
2588
2589         forNode(node) = value;
2590         if (value.m_value)
2591             m_state.setFoundConstants(true);
2592         break;
2593     }
2594         
2595     case GetGetterSetterByOffset: {
2596         StorageAccessData& data = node->storageAccessData();
2597         JSValue result = m_graph.tryGetConstantProperty(forNode(node->child2()), data.offset);
2598         if (result && jsDynamicCast<GetterSetter*>(m_vm, result)) {
2599             setConstant(node, *m_graph.freeze(result));
2600             break;
2601         }
2602         
2603         forNode(node).set(m_graph, m_graph.globalObjectFor(node->origin.semantic)->getterSetterStructure());
2604         break;
2605     }
2606         
2607     case MultiGetByOffset: {
2608         // This code will filter the base value in a manner that is possibly different (either more
2609         // or less precise) than the way it would be filtered if this was strength-reduced to a
2610         // CheckStructure. This is fine. It's legal for different passes over the code to prove
2611         // different things about the code, so long as all of them are sound. That even includes
2612         // one guy proving that code should never execute (due to a contradiction) and another guy
2613         // not finding that contradiction. If someone ever proved that there would be a
2614         // contradiction then there must always be a contradiction even if subsequent passes don't
2615         // realize it. This is the case here.
2616         
2617         // Ordinarily you have to be careful with calling setFoundConstants()
2618         // because of the effect on compile times, but this node is FTL-only.
2619         m_state.setFoundConstants(true);
2620         
2621         UniquedStringImpl* uid = m_graph.identifiers()[node->multiGetByOffsetData().identifierNumber];
2622
2623         AbstractValue base = forNode(node->child1());
2624         RegisteredStructureSet baseSet;
2625         AbstractValue result;
2626         for (const MultiGetByOffsetCase& getCase : node->multiGetByOffsetData().cases) {
2627             RegisteredStructureSet set = getCase.set();
2628             set.filter(base);
2629             if (set.isEmpty())
2630                 continue;
2631             baseSet.merge(set);
2632
2633             switch (getCase.method().kind()) {
2634             case GetByOffsetMethod::Constant: {
2635                 AbstractValue thisResult;
2636                 thisResult.set(
2637                     m_graph,
2638                     *getCase.method().constant(),
2639                     m_state.structureClobberState());
2640                 result.merge(thisResult);
2641                 break;
2642             }
2643
2644             case GetByOffsetMethod::Load: {
2645                 result.merge(
2646                     m_graph.inferredValueForProperty(
2647                         set, uid, m_state.structureClobberState()));
2648                 break;
2649             }
2650
2651             default: {
2652                 result.makeHeapTop();
2653                 break;
2654             } }
2655         }
2656         
2657         if (forNode(node->child1()).changeStructure(m_graph, baseSet) == Contradiction)
2658             m_state.setIsValid(false);
2659         
2660         forNode(node) = result;
2661         break;
2662     }
2663             
2664     case PutByOffset: {
2665         break;
2666     }
2667         
2668     case MultiPutByOffset: {
2669         RegisteredStructureSet newSet;
2670         TransitionVector transitions;
2671         
2672         // Ordinarily you have to be careful with calling setFoundConstants()
2673         // because of the effect on compile times, but this node is FTL-only.
2674         m_state.setFoundConstants(true);
2675         
2676         AbstractValue base = forNode(node->child1());
2677         AbstractValue originalValue = forNode(node->child2());
2678         AbstractValue resultingValue;
2679         
2680         for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
2681             const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
2682             RegisteredStructureSet thisSet = *m_graph.addStructureSet(variant.oldStructure());
2683             thisSet.filter(base);
2684             if (thisSet.isEmpty())
2685                 continue;
2686
2687             AbstractValue thisValue = originalValue;
2688             thisValue.filter(m_graph, variant.requiredType());
2689             resultingValue.merge(thisValue);
2690             
2691             if (variant.kind() == PutByIdVariant::Transition) {
2692                 RegisteredStructure newStructure = m_graph.registerStructure(variant.newStructure());
2693                 if (thisSet.onlyStructure() != newStructure) {
2694                     transitions.append(
2695                         Transition(m_graph.registerStructure(variant.oldStructureForTransition()), newStructure));
2696                 } // else this is really a replace.
2697                 newSet.add(newStructure);
2698             } else {
2699                 ASSERT(variant.kind() == PutByIdVariant::Replace);
2700                 newSet.merge(thisSet);
2701             }
2702         }
2703         
2704         observeTransitions(clobberLimit, transitions);
2705         if (forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction)
2706             m_state.setIsValid(false);
2707         forNode(node->child2()) = resultingValue;
2708         if (!!originalValue && !resultingValue)
2709             m_state.setIsValid(false);
2710         break;
2711     }
2712         
2713     case GetExecutable: {
2714         JSValue value = forNode(node->child1()).value();
2715         if (value) {
2716             JSFunction* function = jsDynamicCast<JSFunction*>(m_vm, value);
2717             if (function) {
2718                 setConstant(node, *m_graph.freeze(function->executable()));
2719                 break;
2720             }
2721         }
2722         forNode(node).setType(m_graph, SpecCellOther);
2723         break;
2724     }
2725     
2726     case CheckCell: {
2727         JSValue value = forNode(node->child1()).value();
2728         if (value == node->cellOperand()->value()) {
2729             m_state.setFoundConstants(true);
2730             ASSERT(value);
2731             break;
2732         }
2733         filterByValue(node->child1(), *node->cellOperand());
2734         break;
2735     }
2736
2737     case CheckNotEmpty: {
2738         AbstractValue& value = forNode(node->child1());
2739         if (!(value.m_type & SpecEmpty)) {
2740             m_state.setFoundConstants(true);
2741             break;
2742         }
2743         
2744         filter(value, ~SpecEmpty);
2745         break;
2746     }
2747
2748     case CheckStringIdent: {
2749         AbstractValue& value = forNode(node->child1());
2750         UniquedStringImpl* uid = node->uidOperand();
2751         ASSERT(!(value.m_type & ~SpecStringIdent)); // Edge filtering should have already ensured this.
2752
2753         JSValue childConstant = value.value();
2754         if (childConstant) {
2755             ASSERT(childConstant.isString());
2756             if (asString(childConstant)->tryGetValueImpl() == uid) {
2757                 m_state.setFoundConstants(true);
2758                 break;
2759             }
2760         }
2761
2762         filter(value, SpecStringIdent);
2763         break;
2764     }
2765
2766     case CheckInBounds: {
2767         JSValue left = forNode(node->child1()).value();
2768         JSValue right = forNode(node->child2()).value();
2769         if (left && right && left.isInt32() && right.isInt32()
2770             && static_cast<uint32_t>(left.asInt32()) < static_cast<uint32_t>(right.asInt32())) {
2771             m_state.setFoundConstants(true);
2772             break;
2773         }
2774         break;
2775     }
2776         
2777     case PutById:
2778     case PutByIdFlush:
2779     case PutByIdDirect: {
2780         AbstractValue& value = forNode(node->child1());
2781         if (value.m_structure.isFinite()) {
2782             PutByIdStatus status = PutByIdStatus::computeFor(
2783                 m_graph.globalObjectFor(node->origin.semantic),
2784                 value.m_structure.toStructureSet(),
2785                 m_graph.identifiers()[node->identifierNumber()],
2786                 node->op() == PutByIdDirect);
2787
2788             if (status.isSimple()) {
2789                 RegisteredStructureSet newSet;
2790                 TransitionVector transitions;
2791                 
2792                 for (unsigned i = status.numVariants(); i--;) {
2793                     const PutByIdVariant& variant = status[i];
2794                     if (variant.kind() == PutByIdVariant::Transition) {
2795                         RegisteredStructure newStructure = m_graph.registerStructure(variant.newStructure());
2796                         transitions.append(
2797                             Transition(
2798                                 m_graph.registerStructure(variant.oldStructureForTransition()), newStructure));
2799                         newSet.add(newStructure);
2800                     } else {
2801                         ASSERT(variant.kind() == PutByIdVariant::Replace);
2802                         newSet.merge(*m_graph.addStructureSet(variant.oldStructure()));
2803                     }
2804                 }
2805                 
2806                 if (status.numVariants() == 1 || isFTL(m_graph.m_plan.mode))
2807                     m_state.setFoundConstants(true);
2808                 
2809                 observeTransitions(clobberLimit, transitions);
2810                 if (forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction)
2811                     m_state.setIsValid(false);
2812                 break;
2813             }
2814         }
2815         
2816         clobberWorld(node->origin.semantic, clobberLimit);
2817         break;
2818     }
2819
2820     case PutByValWithThis:
2821     case PutByIdWithThis:
2822         clobberWorld(node->origin.semantic, clobberLimit);
2823         break;
2824
2825     case PutGetterById:
2826     case PutSetterById:
2827     case PutGetterSetterById:
2828     case PutGetterByVal:
2829     case PutSetterByVal: {
2830         clobberWorld(node->origin.semantic, clobberLimit);
2831         break;
2832     }
2833
2834     case DefineDataProperty:
2835     case DefineAccessorProperty:
2836         clobberWorld(node->origin.semantic, clobberLimit);
2837         break;
2838         
2839     case In: {
2840         // FIXME: We can determine when the property definitely exists based on abstract
2841         // value information.
2842         clobberWorld(node->origin.semantic, clobberLimit);
2843         forNode(node).setType(SpecBoolean);
2844         break;
2845     }
2846
2847     case HasOwnProperty: {
2848         clobberWorld(node->origin.semantic, clobberLimit);
2849         forNode(node).setType(SpecBoolean);
2850         break;
2851     }
2852             
2853     case GetEnumerableLength: {
2854         forNode(node).setType(SpecInt32Only);
2855         break;
2856     }
2857     case HasGenericProperty: {
2858         forNode(node).setType(SpecBoolean);
2859         break;
2860     }
2861     case HasStructureProperty: {
2862         forNode(node).setType(SpecBoolean);
2863         break;
2864     }
2865     case HasIndexedProperty: {
2866         ArrayMode mode = node->arrayMode();
2867         switch (mode.type()) {
2868         case Array::Int32:
2869         case Array::Double:
2870         case Array::Contiguous:
2871         case Array::ArrayStorage: {
2872             break;
2873         }
2874         default: {
2875             clobberWorld(node->origin.semantic, clobberLimit);
2876             break;
2877         }
2878         }
2879         forNode(node).setType(SpecBoolean);
2880         break;
2881     }
2882     case GetDirectPname: {
2883         clobberWorld(node->origin.semantic, clobberLimit);
2884         forNode(node).makeHeapTop();
2885         break;
2886     }
2887     case GetPropertyEnumerator: {
2888         forNode(node).setType(m_graph, SpecCell);
2889         break;
2890     }
2891     case GetEnumeratorStructurePname: {
2892         forNode(node).setType(m_graph, SpecString | SpecOther);
2893         break;
2894     }
2895     case GetEnumeratorGenericPname: {
2896         forNode(node).setType(m_graph, SpecString | SpecOther);
2897         break;
2898     }
2899     case ToIndexString: {
2900         forNode(node).setType(m_graph, SpecString);
2901         break;
2902     }
2903
2904     case GetGlobalVar:
2905         forNode(node).makeHeapTop();
2906         break;
2907
2908     case GetGlobalLexicalVariable:
2909         forNode(node).makeBytecodeTop();
2910         break;
2911
2912     case GetDynamicVar:
2913         clobberWorld(node->origin.semantic, clobberLimit);
2914         forNode(node).makeBytecodeTop();
2915         break;
2916
2917     case PutDynamicVar:
2918         clobberWorld(node->origin.semantic, clobberLimit);
2919         break;
2920
2921     case ResolveScope:
2922         clobberWorld(node->origin.semantic, clobberLimit);
2923         forNode(node).setType(m_graph, SpecObject);
2924         break;
2925
2926     case ResolveScopeForHoistingFuncDeclInEval:
2927         clobberWorld(node->origin.semantic, clobberLimit);
2928         forNode(node).makeBytecodeTop();
2929         break;
2930
2931     case PutGlobalVariable:
2932     case NotifyWrite:
2933         break;
2934
2935     case OverridesHasInstance:
2936         forNode(node).setType(SpecBoolean);
2937         break;
2938             
2939     case InstanceOf:
2940         // Sadly, we don't propagate the fact that we've done InstanceOf
2941         forNode(node).setType(SpecBoolean);
2942         break;
2943
2944     case InstanceOfCustom:
2945         clobberWorld(node->origin.semantic, clobberLimit);
2946         forNode(node).setType(SpecBoolean);
2947         break;
2948             
2949     case Phi:
2950         RELEASE_ASSERT(m_graph.m_form == SSA);
2951         forNode(node) = forNode(NodeFlowProjection(node, NodeFlowProjection::Shadow));
2952         // The state of this node would have already been decided, but it may have become a
2953         // constant, in which case we'd like to know.
2954         if (forNode(node).m_value)
2955             m_state.setFoundConstants(true);
2956         break;
2957         
2958     case Upsilon: {
2959         NodeFlowProjection shadow(node->phi(), NodeFlowProjection::Shadow);
2960         if (shadow.isStillValid()) {
2961             m_state.createValueForNode(shadow);
2962             forNode(shadow) = forNode(node->child1());
2963         }
2964         break;
2965     }
2966         
2967     case Flush:
2968     case PhantomLocal:
2969         break;
2970             
2971     case Call:
2972     case TailCallInlinedCaller:
2973     case Construct:
2974     case CallVarargs:
2975     case CallForwardVarargs:
2976     case TailCallVarargsInlinedCaller:
2977     case ConstructVarargs:
2978     case ConstructForwardVarargs:
2979     case TailCallForwardVarargsInlinedCaller:
2980     case CallEval:
2981     case DirectCall:
2982     case DirectConstruct:
2983     case DirectTailCallInlinedCaller:
2984         clobberWorld(node->origin.semantic, clobberLimit);
2985         forNode(node).makeHeapTop();
2986         break;
2987
2988     case ForceOSRExit:
2989     case CheckBadCell:
2990         m_state.setIsValid(false);
2991         break;
2992         
2993     case InvalidationPoint:
2994         forAllValues(clobberLimit, AbstractValue::observeInvalidationPointFor);
2995         m_state.setStructureClobberState(StructuresAreWatched);
2996         break;
2997
2998     case CheckTraps:
2999     case LogShadowChickenPrologue:
3000     case LogShadowChickenTail:
3001         break;
3002
3003     case ProfileType:
3004     case ProfileControlFlow:
3005     case Phantom:
3006     case CountExecution:
3007     case CheckTierUpInLoop:
3008     case CheckTierUpAtReturn:
3009     case CheckTypeInfoFlags:
3010         break;
3011
3012     case ParseInt: {
3013         AbstractValue value = forNode(node->child1());
3014         if (value.m_type && !(value.m_type & ~SpecInt32Only)) {
3015             JSValue radix;
3016             if (!node->child2())
3017                 radix = jsNumber(0);
3018             else
3019                 radix = forNode(node->child2()).m_value;
3020
3021             if (radix.isNumber()
3022                 && (radix.asNumber() == 0 || radix.asNumber() == 10)) {
3023                 m_state.setFoundConstants(true);
3024                 forNode(node).setType(SpecInt32Only);
3025                 break;
3026             }
3027         }
3028
3029         if (node->child1().useKind() == UntypedUse)
3030             clobberWorld(node->origin.semantic, clobberLimit);
3031         forNode(node).setType(m_graph, SpecBytecodeNumber);
3032         break;
3033     }
3034
3035     case CreateRest:
3036         if (!m_graph.isWatchingHavingABadTimeWatchpoint(node)) {
3037             // This means we're already having a bad time.
3038             clobberWorld(node->origin.semantic, clobberLimit);
3039             forNode(node).setType(m_graph, SpecArray);
3040             break;
3041         }
3042         forNode(node).set(
3043             m_graph,
3044             m_graph.globalObjectFor(node->origin.semantic)->restParameterStructure());
3045         break;
3046             
3047     case Check: {
3048         // Simplify out checks that don't actually do checking.
3049         for (unsigned i = 0; i < AdjacencyList::Size; ++i) {
3050             Edge edge = node->children.child(i);
3051             if (!edge)
3052                 break;
3053             if (edge.isProved() || edge.willNotHaveCheck()) {
3054                 m_state.setFoundConstants(true);
3055                 break;
3056             }
3057         }
3058         break;
3059     }
3060
3061     case SetFunctionName: {
3062         clobberWorld(node->origin.semantic, clobberLimit);
3063         break;
3064     }
3065
3066     case StoreBarrier:
3067     case FencedStoreBarrier: {
3068         filter(node->child1(), SpecCell);
3069         break;
3070     }
3071         
3072     case CheckTierUpAndOSREnter:
3073     case LoopHint:
3074     case ZombieHint:
3075     case ExitOK:
3076         break;
3077
3078     case Unreachable:
3079         // It may be that during a previous run of AI we proved that something was unreachable, but
3080         // during this run of AI we forget that it's unreachable. AI's proofs don't have to get
3081         // monotonically stronger over time. So, we don't assert that AI doesn't reach the
3082         // Unreachable. We have no choice but to take our past proof at face value. Otherwise we'll
3083         // crash whenever AI fails to be as powerful on run K as it was on run K-1.
3084         m_state.setIsValid(false);
3085         break;
3086         
3087     case LastNodeType:
3088     case ArithIMul:
3089     case FiatInt52:
3090         DFG_CRASH(m_graph, node, "Unexpected node type");
3091         break;
3092     }
3093     
3094     return m_state.isValid();
3095 }
3096
3097 template<typename AbstractStateType>
3098 bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned indexInBlock)
3099 {
3100     return executeEffects(indexInBlock, m_state.block()->at(indexInBlock));
3101 }
3102
3103 template<typename AbstractStateType>
3104 bool AbstractInterpreter<AbstractStateType>::execute(unsigned indexInBlock)
3105 {
3106     Node* node = m_state.block()->at(indexInBlock);
3107
3108     startExecuting();
3109     executeEdges(node);
3110     return executeEffects(indexInBlock, node);
3111 }
3112
3113 template<typename AbstractStateType>
3114 bool AbstractInterpreter<AbstractStateType>::execute(Node* node)
3115 {
3116     startExecuting();
3117     executeEdges(node);
3118     return executeEffects(UINT_MAX, node);
3119 }
3120
3121 template<typename AbstractStateType>
3122 void AbstractInterpreter<AbstractStateType>::clobberWorld(
3123     const CodeOrigin&, unsigned clobberLimit)
3124 {
3125     clobberStructures(clobberLimit);
3126 }
3127
3128 template<typename AbstractStateType>
3129 template<typename Functor>
3130 void AbstractInterpreter<AbstractStateType>::forAllValues(
3131     unsigned clobberLimit, Functor& functor)
3132 {
3133     if (clobberLimit >= m_state.block()->size())
3134         clobberLimit = m_state.block()->size();
3135     else
3136         clobberLimit++;
3137     ASSERT(clobberLimit <= m_state.block()->size());
3138     for (size_t i = clobberLimit; i--;) {
3139         NodeFlowProjection::forEach(
3140             m_state.block()->at(i),
3141             [&] (NodeFlowProjection nodeProjection) {
3142                 functor(forNode(nodeProjection));
3143             });
3144     }
3145     if (m_graph.m_form == SSA) {
3146         for (NodeFlowProjection node : m_state.block()->ssa->liveAtHead) {
3147             if (node.isStillValid())
3148                 functor(forNode(node));
3149         }
3150     }
3151     for (size_t i = m_state.variables().numberOfArguments(); i--;)
3152         functor(m_state.variables().argument(i));
3153     for (size_t i = m_state.variables().numberOfLocals(); i--;)
3154         functor(m_state.variables().local(i));
3155 }
3156
3157 template<typename AbstractStateType>
3158 void AbstractInterpreter<AbstractStateType>::clobberStructures(unsigned clobberLimit)
3159 {
3160     forAllValues(clobberLimit, AbstractValue::clobberStructuresFor);
3161     setDidClobber();
3162 }
3163
3164 template<typename AbstractStateType>
3165 void AbstractInterpreter<AbstractStateType>::observeTransition(
3166     unsigned clobberLimit, RegisteredStructure from, RegisteredStructure to)
3167 {
3168     AbstractValue::TransitionObserver transitionObserver(from, to);
3169     forAllValues(clobberLimit, transitionObserver);
3170     
3171     ASSERT(!from->dfgShouldWatch()); // We don't need to claim to be in a clobbered state because 'from' was never watchable (during the time we were compiling), hence no constants ever introduced into the DFG IR that ever had a watchable structure would ever have the same structure as from.
3172 }
3173
3174 template<typename AbstractStateType>
3175 void AbstractInterpreter<AbstractStateType>::observeTransitions(
3176     unsigned clobberLimit, const TransitionVector& vector)
3177 {
3178     AbstractValue::TransitionsObserver transitionsObserver(vector);
3179     forAllValues(clobberLimit, transitionsObserver);
3180     
3181     if (!ASSERT_DISABLED) {
3182         // We don't need to claim to be in a clobbered state because none of the Transition::previous structures are watchable.
3183         for (unsigned i = vector.size(); i--;)
3184             ASSERT(!vector[i].previous->dfgShouldWatch());
3185     }
3186 }
3187
3188 template<typename AbstractStateType>
3189 void AbstractInterpreter<AbstractStateType>::setDidClobber()
3190 {
3191     m_state.setDidClobber(true);
3192     m_state.setStructureClobberState(StructuresAreClobbered);
3193 }
3194
3195 template<typename AbstractStateType>
3196 void AbstractInterpreter<AbstractStateType>::dump(PrintStream& out) const
3197 {
3198     const_cast<AbstractInterpreter<AbstractStateType>*>(this)->dump(out);
3199 }
3200
3201 template<typename AbstractStateType>
3202 void AbstractInterpreter<AbstractStateType>::dump(PrintStream& out)
3203 {
3204     CommaPrinter comma(" ");
3205     HashSet<NodeFlowProjection> seen;
3206     if (m_graph.m_form == SSA) {
3207         for (NodeFlowProjection node : m_state.block()->ssa->liveAtHead) {
3208             seen.add(node);
3209             AbstractValue& value = forNode(node);
3210             if (value.isClear())
3211                 continue;
3212             out.print(comma, node, ":", value);
3213         }
3214     }
3215     for (size_t i = 0; i < m_state.block()->size(); ++i) {
3216         NodeFlowProjection::forEach(
3217             m_state.block()->at(i), [&] (NodeFlowProjection nodeProjection) {
3218                 seen.add(nodeProjection);
3219                 AbstractValue& value = forNode(nodeProjection);
3220                 if (value.isClear())
3221                     return;
3222                 out.print(comma, nodeProjection, ":", value);
3223             });
3224     }
3225     if (m_graph.m_form == SSA) {
3226         for (NodeFlowProjection node : m_state.block()->ssa->liveAtTail) {
3227             if (seen.contains(node))
3228                 continue;
3229             AbstractValue& value = forNode(node);
3230             if (value.isClear())
3231                 continue;
3232             out.print(comma, node, ":", value);
3233         }
3234     }
3235 }
3236
3237 template<typename AbstractStateType>
3238 FiltrationResult AbstractInterpreter<AbstractStateType>::filter(
3239     AbstractValue& value, const RegisteredStructureSet& set, SpeculatedType admittedTypes)
3240 {
3241     if (value.filter(m_graph, set, admittedTypes) == FiltrationOK)
3242         return FiltrationOK;
3243     m_state.setIsValid(false);
3244     return Contradiction;
3245 }
3246
3247 template<typename AbstractStateType>
3248 FiltrationResult AbstractInterpreter<AbstractStateType>::filterArrayModes(
3249     AbstractValue& value, ArrayModes arrayModes)
3250 {
3251     if (value.filterArrayModes(arrayModes) == FiltrationOK)
3252         return FiltrationOK;
3253     m_state.setIsValid(false);
3254     return Contradiction;
3255 }
3256
3257 template<typename AbstractStateType>
3258 FiltrationResult AbstractInterpreter<AbstractStateType>::filter(
3259     AbstractValue& value, SpeculatedType type)
3260 {
3261     if (value.filter(type) == FiltrationOK)
3262         return FiltrationOK;
3263     m_state.setIsValid(false);
3264     return Contradiction;
3265 }
3266
3267 template<typename AbstractStateType>
3268 FiltrationResult AbstractInterpreter<AbstractStateType>::filterByValue(
3269     AbstractValue& abstractValue, FrozenValue concreteValue)
3270 {
3271     if (abstractValue.filterByValue(concreteValue) == FiltrationOK)
3272         return FiltrationOK;
3273     m_state.setIsValid(false);
3274     return Contradiction;
3275 }
3276
3277 template<typename AbstractStateType>
3278 FiltrationResult AbstractInterpreter<AbstractStateType>::filterClassInfo(
3279     AbstractValue& value, const ClassInfo* classInfo)
3280 {
3281     if (value.filterClassInfo(m_graph, classInfo) == FiltrationOK)
3282         return FiltrationOK;
3283     m_state.setIsValid(false);
3284     return Contradiction;
3285 }
3286
3287 template<typename AbstractStateType>
3288 void AbstractInterpreter<AbstractStateType>::executeDoubleUnaryOpEffects(Node* node, double(*equivalentFunction)(double))
3289 {
3290     JSValue child = forNode(node->child1()).value();
3291     if (std::optional<double> number = child.toNumberFromPrimitive()) {
3292         setConstant(node, jsDoubleNumber(equivalentFunction(*number)));
3293         return;
3294     }
3295     SpeculatedType type = SpecFullNumber;
3296     if (node->child1().useKind() == DoubleRepUse)
3297         type = typeOfDoubleUnaryOp(forNode(node->child1()).m_type);
3298     forNode(node).setType(type);
3299 }
3300
3301 } } // namespace JSC::DFG
3302
3303 #endif // ENABLE(DFG_JIT)