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