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