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