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