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