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