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