53c845f56eb4040853f41721200d5554018a9791
[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 ArithSqrt: {
766         JSValue child = forNode(node->child1()).value();
767         if (child && child.isNumber()) {
768             setConstant(node, jsDoubleNumber(sqrt(child.asNumber())));
769             break;
770         }
771         forNode(node).setType(typeOfDoubleUnaryOp(forNode(node->child1()).m_type));
772         break;
773     }
774         
775     case ArithFRound: {
776         JSValue child = forNode(node->child1()).value();
777         if (child && child.isNumber()) {
778             setConstant(node, jsDoubleNumber(static_cast<float>(child.asNumber())));
779             break;
780         }
781         forNode(node).setType(typeOfDoubleFRound(forNode(node->child1()).m_type));
782         break;
783     }
784         
785     case ArithSin: {
786         JSValue child = forNode(node->child1()).value();
787         if (false && child && child.isNumber()) {
788             setConstant(node, jsDoubleNumber(sin(child.asNumber())));
789             break;
790         }
791         forNode(node).setType(typeOfDoubleUnaryOp(forNode(node->child1()).m_type));
792         break;
793     }
794     
795     case ArithCos: {
796         JSValue child = forNode(node->child1()).value();
797         if (false && child && child.isNumber()) {
798             setConstant(node, jsDoubleNumber(cos(child.asNumber())));
799             break;
800         }
801         forNode(node).setType(typeOfDoubleUnaryOp(forNode(node->child1()).m_type));
802         break;
803     }
804
805     case ArithLog: {
806         JSValue child = forNode(node->child1()).value();
807         if (child && child.isNumber()) {
808             setConstant(node, jsDoubleNumber(log(child.asNumber())));
809             break;
810         }
811         forNode(node).setType(typeOfDoubleUnaryOp(forNode(node->child1()).m_type));
812         break;
813     }
814             
815     case LogicalNot: {
816         switch (booleanResult(node, forNode(node->child1()))) {
817         case DefinitelyTrue:
818             setConstant(node, jsBoolean(false));
819             break;
820         case DefinitelyFalse:
821             setConstant(node, jsBoolean(true));
822             break;
823         default:
824             forNode(node).setType(SpecBoolean);
825             break;
826         }
827         break;
828     }
829         
830     case IsUndefined:
831     case IsBoolean:
832     case IsNumber:
833     case IsString:
834     case IsObject:
835     case IsObjectOrNull:
836     case IsFunction: {
837         AbstractValue child = forNode(node->child1());
838         if (child.value()) {
839             bool constantWasSet = true;
840             switch (node->op()) {
841             case IsUndefined:
842                 setConstant(node, jsBoolean(
843                     child.value().isCell()
844                     ? child.value().asCell()->structure()->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node->origin.semantic))
845                     : child.value().isUndefined()));
846                 break;
847             case IsBoolean:
848                 setConstant(node, jsBoolean(child.value().isBoolean()));
849                 break;
850             case IsNumber:
851                 setConstant(node, jsBoolean(child.value().isNumber()));
852                 break;
853             case IsString:
854                 setConstant(node, jsBoolean(isJSString(child.value())));
855                 break;
856             case IsObject:
857                 setConstant(node, jsBoolean(child.value().isObject()));
858                 break;
859             case IsObjectOrNull:
860                 if (child.value().isObject()) {
861                     JSObject* object = asObject(child.value());
862                     if (object->type() == JSFunctionType)
863                         setConstant(node, jsBoolean(false));
864                     else if (!(object->inlineTypeFlags() & TypeOfShouldCallGetCallData))
865                         setConstant(node, jsBoolean(!child.value().asCell()->structure()->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node->origin.semantic))));
866                     else {
867                         // FIXME: This could just call getCallData.
868                         // https://bugs.webkit.org/show_bug.cgi?id=144457
869                         constantWasSet = false;
870                     }
871                 } else
872                     setConstant(node, jsBoolean(child.value().isNull()));
873                 break;
874             case IsFunction:
875                 if (child.value().isObject()) {
876                     JSObject* object = asObject(child.value());
877                     if (object->type() == JSFunctionType)
878                         setConstant(node, jsBoolean(true));
879                     else if (!(object->inlineTypeFlags() & TypeOfShouldCallGetCallData))
880                         setConstant(node, jsBoolean(false));
881                     else {
882                         // FIXME: This could just call getCallData.
883                         // https://bugs.webkit.org/show_bug.cgi?id=144457
884                         constantWasSet = false;
885                     }
886                 } else
887                     setConstant(node, jsBoolean(false));
888                 break;
889             default:
890                 constantWasSet = false;
891                 break;
892             }
893             if (constantWasSet)
894                 break;
895         }
896         
897         bool constantWasSet = false;
898         switch (node->op()) {
899         case IsUndefined:
900             // FIXME: Use the masquerades-as-undefined watchpoint thingy.
901             // https://bugs.webkit.org/show_bug.cgi?id=144456
902             
903             if (!(child.m_type & (SpecOther | SpecObjectOther))) {
904                 setConstant(node, jsBoolean(false));
905                 constantWasSet = true;
906                 break;
907             }
908             
909             break;
910         case IsBoolean:
911             if (!(child.m_type & ~SpecBoolean)) {
912                 setConstant(node, jsBoolean(true));
913                 constantWasSet = true;
914                 break;
915             }
916             
917             if (!(child.m_type & SpecBoolean)) {
918                 setConstant(node, jsBoolean(false));
919                 constantWasSet = true;
920                 break;
921             }
922             
923             break;
924         case IsNumber:
925             if (!(child.m_type & ~SpecFullNumber)) {
926                 setConstant(node, jsBoolean(true));
927                 constantWasSet = true;
928                 break;
929             }
930             
931             if (!(child.m_type & SpecFullNumber)) {
932                 setConstant(node, jsBoolean(false));
933                 constantWasSet = true;
934                 break;
935             }
936             
937             break;
938         case IsString:
939             if (!(child.m_type & ~SpecString)) {
940                 setConstant(node, jsBoolean(true));
941                 constantWasSet = true;
942                 break;
943             }
944             
945             if (!(child.m_type & SpecString)) {
946                 setConstant(node, jsBoolean(false));
947                 constantWasSet = true;
948                 break;
949             }
950             
951             break;
952         case IsObject:
953             if (!(child.m_type & ~SpecObject)) {
954                 setConstant(node, jsBoolean(true));
955                 constantWasSet = true;
956                 break;
957             }
958             
959             if (!(child.m_type & SpecObject)) {
960                 setConstant(node, jsBoolean(false));
961                 constantWasSet = true;
962                 break;
963             }
964             
965             break;
966         case IsObjectOrNull:
967             // FIXME: Use the masquerades-as-undefined watchpoint thingy.
968             // https://bugs.webkit.org/show_bug.cgi?id=144456
969             
970             if (!(child.m_type & ~(SpecObject - SpecObjectOther - SpecFunction))) {
971                 setConstant(node, jsBoolean(true));
972                 constantWasSet = true;
973                 break;
974             }
975             
976             if (!(child.m_type & (SpecObject - SpecFunction))) {
977                 setConstant(node, jsBoolean(false));
978                 constantWasSet = true;
979                 break;
980             }
981             
982             break;
983         case IsFunction:
984             if (!(child.m_type & ~SpecFunction)) {
985                 setConstant(node, jsBoolean(true));
986                 constantWasSet = true;
987                 break;
988             }
989             
990             if (!(child.m_type & (SpecFunction | SpecObjectOther))) {
991                 setConstant(node, jsBoolean(false));
992                 constantWasSet = true;
993                 break;
994             }
995             break;
996         default:
997             break;
998         }
999         if (constantWasSet)
1000             break;
1001         
1002         forNode(node).setType(SpecBoolean);
1003         break;
1004     }
1005
1006     case TypeOf: {
1007         VM* vm = m_codeBlock->vm();
1008         JSValue child = forNode(node->child1()).value();
1009         AbstractValue& abstractChild = forNode(node->child1());
1010         if (child) {
1011             JSValue typeString = jsTypeStringForValue(*vm, m_codeBlock->globalObjectFor(node->origin.semantic), child);
1012             setConstant(node, *m_graph.freeze(typeString));
1013             break;
1014         }
1015         
1016         if (isFullNumberSpeculation(abstractChild.m_type)) {
1017             setConstant(node, *m_graph.freeze(vm->smallStrings.numberString()));
1018             break;
1019         }
1020         
1021         if (isStringSpeculation(abstractChild.m_type)) {
1022             setConstant(node, *m_graph.freeze(vm->smallStrings.stringString()));
1023             break;
1024         }
1025
1026         // FIXME: We could use the masquerades-as-undefined watchpoint here.
1027         // https://bugs.webkit.org/show_bug.cgi?id=144456
1028         if (!(abstractChild.m_type & ~(SpecObject - SpecObjectOther))) {
1029             setConstant(node, *m_graph.freeze(vm->smallStrings.objectString()));
1030             break;
1031         }
1032         
1033         if (isFunctionSpeculation(abstractChild.m_type)) {
1034             setConstant(node, *m_graph.freeze(vm->smallStrings.functionString()));
1035             break;
1036         }
1037         
1038         if (isBooleanSpeculation(abstractChild.m_type)) {
1039             setConstant(node, *m_graph.freeze(vm->smallStrings.booleanString()));
1040             break;
1041         }
1042
1043         forNode(node).setType(m_graph, SpecStringIdent);
1044         break;
1045     }
1046             
1047     case CompareLess:
1048     case CompareLessEq:
1049     case CompareGreater:
1050     case CompareGreaterEq:
1051     case CompareEq:
1052     case CompareEqConstant: {
1053         JSValue leftConst = forNode(node->child1()).value();
1054         JSValue rightConst = forNode(node->child2()).value();
1055         if (leftConst && rightConst) {
1056             if (leftConst.isNumber() && rightConst.isNumber()) {
1057                 double a = leftConst.asNumber();
1058                 double b = rightConst.asNumber();
1059                 switch (node->op()) {
1060                 case CompareLess:
1061                     setConstant(node, jsBoolean(a < b));
1062                     break;
1063                 case CompareLessEq:
1064                     setConstant(node, jsBoolean(a <= b));
1065                     break;
1066                 case CompareGreater:
1067                     setConstant(node, jsBoolean(a > b));
1068                     break;
1069                 case CompareGreaterEq:
1070                     setConstant(node, jsBoolean(a >= b));
1071                     break;
1072                 case CompareEq:
1073                     setConstant(node, jsBoolean(a == b));
1074                     break;
1075                 default:
1076                     RELEASE_ASSERT_NOT_REACHED();
1077                     break;
1078                 }
1079                 break;
1080             }
1081             
1082             if (node->op() == CompareEq && leftConst.isString() && rightConst.isString()) {
1083                 const StringImpl* a = asString(leftConst)->tryGetValueImpl();
1084                 const StringImpl* b = asString(rightConst)->tryGetValueImpl();
1085                 if (a && b) {
1086                     setConstant(node, jsBoolean(WTF::equal(a, b)));
1087                     break;
1088                 }
1089             }
1090         }
1091         
1092         if (node->op() == CompareEqConstant || node->op() == CompareEq) {
1093             SpeculatedType leftType = forNode(node->child1()).m_type;
1094             SpeculatedType rightType = forNode(node->child2()).m_type;
1095             if (!valuesCouldBeEqual(leftType, rightType)) {
1096                 setConstant(node, jsBoolean(false));
1097                 break;
1098             }
1099         }
1100         
1101         forNode(node).setType(SpecBoolean);
1102         break;
1103     }
1104             
1105     case CompareStrictEq: {
1106         Node* leftNode = node->child1().node();
1107         Node* rightNode = node->child2().node();
1108         JSValue left = forNode(leftNode).value();
1109         JSValue right = forNode(rightNode).value();
1110         if (left && right) {
1111             if (left.isString() && right.isString()) {
1112                 // We need this case because JSValue::strictEqual is otherwise too racy for
1113                 // string comparisons.
1114                 const StringImpl* a = asString(left)->tryGetValueImpl();
1115                 const StringImpl* b = asString(right)->tryGetValueImpl();
1116                 if (a && b) {
1117                     setConstant(node, jsBoolean(WTF::equal(a, b)));
1118                     break;
1119                 }
1120             } else {
1121                 setConstant(node, jsBoolean(JSValue::strictEqual(0, left, right)));
1122                 break;
1123             }
1124         }
1125         
1126         SpeculatedType leftLUB = leastUpperBoundOfStrictlyEquivalentSpeculations(forNode(leftNode).m_type);
1127         SpeculatedType rightLUB = leastUpperBoundOfStrictlyEquivalentSpeculations(forNode(rightNode).m_type);
1128         if (!(leftLUB & rightLUB)) {
1129             setConstant(node, jsBoolean(false));
1130             break;
1131         }
1132         
1133         forNode(node).setType(SpecBoolean);
1134         break;
1135     }
1136         
1137     case StringCharCodeAt:
1138         forNode(node).setType(SpecInt32);
1139         break;
1140         
1141     case StringFromCharCode:
1142         forNode(node).setType(m_graph, SpecString);
1143         break;
1144
1145     case StringCharAt:
1146         forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
1147         break;
1148             
1149     case GetByVal: {
1150         switch (node->arrayMode().type()) {
1151         case Array::SelectUsingPredictions:
1152         case Array::Unprofiled:
1153         case Array::Undecided:
1154             RELEASE_ASSERT_NOT_REACHED();
1155             break;
1156         case Array::ForceExit:
1157             m_state.setIsValid(false);
1158             break;
1159         case Array::Generic:
1160             clobberWorld(node->origin.semantic, clobberLimit);
1161             forNode(node).makeHeapTop();
1162             break;
1163         case Array::String:
1164             if (node->arrayMode().isOutOfBounds()) {
1165                 // If the watchpoint was still valid we could totally set this to be
1166                 // SpecString | SpecOther. Except that we'd have to be careful. If we
1167                 // tested the watchpoint state here then it could change by the time
1168                 // we got to the backend. So to do this right, we'd have to get the
1169                 // fixup phase to check the watchpoint state and then bake into the
1170                 // GetByVal operation the fact that we're using a watchpoint, using
1171                 // something like Array::SaneChain (except not quite, because that
1172                 // implies an in-bounds access). None of this feels like it's worth it,
1173                 // so we're going with TOP for now. The same thing applies to
1174                 // clobbering the world.
1175                 clobberWorld(node->origin.semantic, clobberLimit);
1176                 forNode(node).makeHeapTop();
1177             } else
1178                 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
1179             break;
1180         case Array::DirectArguments:
1181         case Array::ScopedArguments:
1182             forNode(node).makeHeapTop();
1183             break;
1184         case Array::Int32:
1185             if (node->arrayMode().isOutOfBounds()) {
1186                 clobberWorld(node->origin.semantic, clobberLimit);
1187                 forNode(node).makeHeapTop();
1188             } else
1189                 forNode(node).setType(SpecInt32);
1190             break;
1191         case Array::Double:
1192             if (node->arrayMode().isOutOfBounds()) {
1193                 clobberWorld(node->origin.semantic, clobberLimit);
1194                 forNode(node).makeHeapTop();
1195             } else if (node->arrayMode().isSaneChain())
1196                 forNode(node).setType(SpecBytecodeDouble);
1197             else
1198                 forNode(node).setType(SpecDoubleReal);
1199             break;
1200         case Array::Contiguous:
1201         case Array::ArrayStorage:
1202         case Array::SlowPutArrayStorage:
1203             if (node->arrayMode().isOutOfBounds())
1204                 clobberWorld(node->origin.semantic, clobberLimit);
1205             forNode(node).makeHeapTop();
1206             break;
1207         case Array::Int8Array:
1208             forNode(node).setType(SpecInt32);
1209             break;
1210         case Array::Int16Array:
1211             forNode(node).setType(SpecInt32);
1212             break;
1213         case Array::Int32Array:
1214             forNode(node).setType(SpecInt32);
1215             break;
1216         case Array::Uint8Array:
1217             forNode(node).setType(SpecInt32);
1218             break;
1219         case Array::Uint8ClampedArray:
1220             forNode(node).setType(SpecInt32);
1221             break;
1222         case Array::Uint16Array:
1223             forNode(node).setType(SpecInt32);
1224             break;
1225         case Array::Uint32Array:
1226             if (node->shouldSpeculateInt32())
1227                 forNode(node).setType(SpecInt32);
1228             else if (enableInt52() && node->shouldSpeculateMachineInt())
1229                 forNode(node).setType(SpecInt52);
1230             else
1231                 forNode(node).setType(SpecInt52AsDouble);
1232             break;
1233         case Array::Float32Array:
1234             forNode(node).setType(SpecFullDouble);
1235             break;
1236         case Array::Float64Array:
1237             forNode(node).setType(SpecFullDouble);
1238             break;
1239         default:
1240             RELEASE_ASSERT_NOT_REACHED();
1241             break;
1242         }
1243         break;
1244     }
1245             
1246     case PutByValDirect:
1247     case PutByVal:
1248     case PutByValAlias: {
1249         switch (node->arrayMode().modeForPut().type()) {
1250         case Array::ForceExit:
1251             m_state.setIsValid(false);
1252             break;
1253         case Array::Generic:
1254             clobberWorld(node->origin.semantic, clobberLimit);
1255             break;
1256         case Array::Int32:
1257             if (node->arrayMode().isOutOfBounds())
1258                 clobberWorld(node->origin.semantic, clobberLimit);
1259             break;
1260         case Array::Double:
1261             if (node->arrayMode().isOutOfBounds())
1262                 clobberWorld(node->origin.semantic, clobberLimit);
1263             break;
1264         case Array::Contiguous:
1265         case Array::ArrayStorage:
1266             if (node->arrayMode().isOutOfBounds())
1267                 clobberWorld(node->origin.semantic, clobberLimit);
1268             break;
1269         case Array::SlowPutArrayStorage:
1270             if (node->arrayMode().mayStoreToHole())
1271                 clobberWorld(node->origin.semantic, clobberLimit);
1272             break;
1273         default:
1274             break;
1275         }
1276         break;
1277     }
1278             
1279     case ArrayPush:
1280         clobberWorld(node->origin.semantic, clobberLimit);
1281         forNode(node).setType(SpecBytecodeNumber);
1282         break;
1283             
1284     case ArrayPop:
1285         clobberWorld(node->origin.semantic, clobberLimit);
1286         forNode(node).makeHeapTop();
1287         break;
1288         
1289     case GetMyArgumentByVal: {
1290         JSValue index = forNode(node->child2()).m_value;
1291         InlineCallFrame* inlineCallFrame = node->child1()->origin.semantic.inlineCallFrame;
1292
1293         if (index && index.isInt32()) {
1294             // This pretends to return TOP for accesses that are actually proven out-of-bounds because
1295             // that's the conservative thing to do. Otherwise we'd need to write more code to mark such
1296             // paths as unreachable, and it's almost certainly not worth the effort.
1297             
1298             if (inlineCallFrame) {
1299                 if (index.asUInt32() < inlineCallFrame->arguments.size() - 1) {
1300                     forNode(node) = m_state.variables().operand(
1301                         virtualRegisterForArgument(index.asInt32() + 1) + inlineCallFrame->stackOffset);
1302                     m_state.setFoundConstants(true);
1303                     break;
1304                 }
1305             } else {
1306                 if (index.asUInt32() < m_state.variables().numberOfArguments() - 1) {
1307                     forNode(node) = m_state.variables().argument(index.asInt32() + 1);
1308                     m_state.setFoundConstants(true);
1309                     break;
1310                 }
1311             }
1312         }
1313         
1314         if (inlineCallFrame) {
1315             // We have a bound on the types even though it's random access. Take advantage of this.
1316             
1317             AbstractValue result;
1318             for (unsigned i = inlineCallFrame->arguments.size(); i-- > 1;) {
1319                 result.merge(
1320                     m_state.variables().operand(
1321                         virtualRegisterForArgument(i) + inlineCallFrame->stackOffset));
1322             }
1323             
1324             if (result.value())
1325                 m_state.setFoundConstants(true);
1326             forNode(node) = result;
1327             break;
1328         }
1329         
1330         forNode(node).makeHeapTop();
1331         break;
1332     }
1333             
1334     case RegExpExec:
1335         forNode(node).makeHeapTop();
1336         break;
1337
1338     case RegExpTest:
1339         forNode(node).setType(SpecBoolean);
1340         break;
1341             
1342     case Jump:
1343         break;
1344             
1345     case Branch: {
1346         Node* child = node->child1().node();
1347         BooleanResult result = booleanResult(node, forNode(child));
1348         if (result == DefinitelyTrue) {
1349             m_state.setBranchDirection(TakeTrue);
1350             break;
1351         }
1352         if (result == DefinitelyFalse) {
1353             m_state.setBranchDirection(TakeFalse);
1354             break;
1355         }
1356         // FIXME: The above handles the trivial cases of sparse conditional
1357         // constant propagation, but we can do better:
1358         // We can specialize the source variable's value on each direction of
1359         // the branch.
1360         m_state.setBranchDirection(TakeBoth);
1361         break;
1362     }
1363         
1364     case Switch: {
1365         // Nothing to do for now.
1366         // FIXME: Do sparse conditional things.
1367         break;
1368     }
1369             
1370     case Return:
1371         m_state.setIsValid(false);
1372         break;
1373         
1374     case Throw:
1375     case ThrowReferenceError:
1376         m_state.setIsValid(false);
1377         break;
1378             
1379     case ToPrimitive: {
1380         JSValue childConst = forNode(node->child1()).value();
1381         if (childConst && childConst.isNumber()) {
1382             setConstant(node, childConst);
1383             break;
1384         }
1385         
1386         ASSERT(node->child1().useKind() == UntypedUse);
1387         
1388         if (!forNode(node->child1()).m_type) {
1389             m_state.setIsValid(false);
1390             break;
1391         }
1392         
1393         if (!(forNode(node->child1()).m_type & ~(SpecFullNumber | SpecBoolean | SpecString | SpecCellOther))) {
1394             m_state.setFoundConstants(true);
1395             forNode(node) = forNode(node->child1());
1396             break;
1397         }
1398         
1399         clobberWorld(node->origin.semantic, clobberLimit);
1400         
1401         forNode(node).setType(m_graph, (SpecHeapTop & ~SpecCell) | SpecString | SpecCellOther);
1402         break;
1403     }
1404         
1405     case ToString:
1406     case CallStringConstructor: {
1407         switch (node->child1().useKind()) {
1408         case StringObjectUse:
1409             // This also filters that the StringObject has the primordial StringObject
1410             // structure.
1411             filter(
1412                 node->child1(),
1413                 m_graph.globalObjectFor(node->origin.semantic)->stringObjectStructure());
1414             break;
1415         case StringOrStringObjectUse:
1416             break;
1417         case CellUse:
1418         case UntypedUse:
1419             clobberWorld(node->origin.semantic, clobberLimit);
1420             break;
1421         default:
1422             RELEASE_ASSERT_NOT_REACHED();
1423             break;
1424         }
1425         forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
1426         break;
1427     }
1428         
1429     case NewStringObject: {
1430         ASSERT(node->structure()->classInfo() == StringObject::info());
1431         forNode(node).set(m_graph, node->structure());
1432         break;
1433     }
1434             
1435     case NewArray:
1436         forNode(node).set(
1437             m_graph,
1438             m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()));
1439         break;
1440         
1441     case NewArrayBuffer:
1442         forNode(node).set(
1443             m_graph,
1444             m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()));
1445         break;
1446
1447     case NewArrayWithSize:
1448         forNode(node).setType(m_graph, SpecArray);
1449         break;
1450         
1451     case NewTypedArray:
1452         switch (node->child1().useKind()) {
1453         case Int32Use:
1454             break;
1455         case UntypedUse:
1456             clobberWorld(node->origin.semantic, clobberLimit);
1457             break;
1458         default:
1459             RELEASE_ASSERT_NOT_REACHED();
1460             break;
1461         }
1462         forNode(node).set(
1463             m_graph,
1464             m_graph.globalObjectFor(node->origin.semantic)->typedArrayStructure(
1465                 node->typedArrayType()));
1466         break;
1467             
1468     case NewRegexp:
1469         forNode(node).set(m_graph, m_graph.globalObjectFor(node->origin.semantic)->regExpStructure());
1470         break;
1471             
1472     case ToThis: {
1473         AbstractValue& source = forNode(node->child1());
1474         AbstractValue& destination = forNode(node);
1475             
1476         if (m_graph.executableFor(node->origin.semantic)->isStrictMode())
1477             destination.makeHeapTop();
1478         else {
1479             destination = source;
1480             destination.merge(SpecObject);
1481         }
1482         break;
1483     }
1484
1485     case CreateThis: {
1486         // FIXME: We can fold this to NewObject if the incoming callee is a constant.
1487         forNode(node).setType(m_graph, SpecFinalObject);
1488         break;
1489     }
1490         
1491     case NewObject:
1492         ASSERT(node->structure());
1493         forNode(node).set(m_graph, node->structure());
1494         break;
1495         
1496     case PhantomNewObject:
1497     case PhantomNewFunction:
1498     case PhantomCreateActivation:
1499     case PhantomDirectArguments:
1500     case PhantomClonedArguments:
1501     case BottomValue:
1502         m_state.setDidClobber(true); // Prevent constant folding.
1503         // This claims to return bottom.
1504         break;
1505         
1506     case PutHint:
1507         break;
1508         
1509     case MaterializeNewObject: {
1510         StructureSet set;
1511         
1512         m_phiChildren->forAllTransitiveIncomingValues(
1513             m_graph.varArgChild(node, 0).node(),
1514             [&] (Node* incoming) {
1515                 set.add(incoming->castConstant<Structure*>());
1516             });
1517         
1518         forNode(node).set(m_graph, set);
1519         break;
1520     }
1521
1522     case CreateActivation:
1523     case MaterializeCreateActivation:
1524         forNode(node).set(
1525             m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->activationStructure());
1526         break;
1527         
1528     case CreateDirectArguments:
1529         forNode(node).set(m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->directArgumentsStructure());
1530         break;
1531         
1532     case CreateScopedArguments:
1533         forNode(node).set(m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->scopedArgumentsStructure());
1534         break;
1535         
1536     case CreateClonedArguments:
1537         forNode(node).setType(m_graph, SpecObjectOther);
1538         break;
1539         
1540     case NewFunction:
1541         forNode(node).set(
1542             m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->functionStructure());
1543         break;
1544         
1545     case GetCallee:
1546         if (FunctionExecutable* executable = jsDynamicCast<FunctionExecutable*>(m_codeBlock->ownerExecutable())) {
1547             InferredValue* singleton = executable->singletonFunction();
1548             if (JSValue value = singleton->inferredValue()) {
1549                 m_graph.watchpoints().addLazily(singleton);
1550                 JSFunction* function = jsCast<JSFunction*>(value);
1551                 setConstant(node, *m_graph.freeze(function));
1552                 break;
1553             }
1554         }
1555         forNode(node).setType(m_graph, SpecFunction);
1556         break;
1557         
1558     case GetArgumentCount:
1559         forNode(node).setType(SpecInt32);
1560         break;
1561         
1562     case GetGetter: {
1563         JSValue base = forNode(node->child1()).m_value;
1564         if (base) {
1565             GetterSetter* getterSetter = jsCast<GetterSetter*>(base);
1566             if (!getterSetter->isGetterNull()) {
1567                 setConstant(node, *m_graph.freeze(getterSetter->getterConcurrently()));
1568                 break;
1569             }
1570         }
1571         
1572         forNode(node).setType(m_graph, SpecObject);
1573         break;
1574     }
1575         
1576     case GetSetter: {
1577         JSValue base = forNode(node->child1()).m_value;
1578         if (base) {
1579             GetterSetter* getterSetter = jsCast<GetterSetter*>(base);
1580             if (!getterSetter->isSetterNull()) {
1581                 setConstant(node, *m_graph.freeze(getterSetter->setterConcurrently()));
1582                 break;
1583             }
1584         }
1585         
1586         forNode(node).setType(m_graph, SpecObject);
1587         break;
1588     }
1589         
1590     case GetScope:
1591         if (JSValue base = forNode(node->child1()).m_value) {
1592             if (JSFunction* function = jsDynamicCast<JSFunction*>(base)) {
1593                 setConstant(node, *m_graph.freeze(function->scope()));
1594                 break;
1595             }
1596         }
1597         forNode(node).setType(m_graph, SpecObjectOther);
1598         break;
1599
1600     case SkipScope: {
1601         JSValue child = forNode(node->child1()).value();
1602         if (child) {
1603             setConstant(node, *m_graph.freeze(JSValue(jsCast<JSScope*>(child.asCell())->next())));
1604             break;
1605         }
1606         forNode(node).setType(m_graph, SpecObjectOther);
1607         break;
1608     }
1609
1610     case GetClosureVar:
1611         if (JSValue value = m_graph.tryGetConstantClosureVar(forNode(node->child1()), node->scopeOffset())) {
1612             setConstant(node, *m_graph.freeze(value));
1613             break;
1614         }
1615         forNode(node).makeHeapTop();
1616         break;
1617             
1618     case PutClosureVar:
1619         break;
1620         
1621     case GetFromArguments:
1622         forNode(node).makeHeapTop();
1623         break;
1624         
1625     case PutToArguments:
1626         break;
1627             
1628     case GetById:
1629     case GetByIdFlush: {
1630         if (!node->prediction()) {
1631             m_state.setIsValid(false);
1632             break;
1633         }
1634         
1635         AbstractValue& value = forNode(node->child1());
1636         if (!value.m_structure.isTop() && !value.m_structure.isClobbered()
1637             && (node->child1().useKind() == CellUse || !(value.m_type & ~SpecCell))) {
1638             GetByIdStatus status = GetByIdStatus::computeFor(
1639                 value.m_structure.set(), m_graph.identifiers()[node->identifierNumber()]);
1640             if (status.isSimple()) {
1641                 // Figure out what the result is going to be - is it TOP, a constant, or maybe
1642                 // something more subtle?
1643                 AbstractValue result;
1644                 for (unsigned i = status.numVariants(); i--;) {
1645                     DFG_ASSERT(m_graph, node, !status[i].alternateBase());
1646                     JSValue constantResult =
1647                         m_graph.tryGetConstantProperty(value, status[i].offset());
1648                     if (!constantResult) {
1649                         result.makeHeapTop();
1650                         break;
1651                     }
1652                     
1653                     AbstractValue thisResult;
1654                     thisResult.set(
1655                         m_graph, *m_graph.freeze(constantResult),
1656                         m_state.structureClobberState());
1657                     result.merge(thisResult);
1658                 }
1659                 if (status.numVariants() == 1 || isFTL(m_graph.m_plan.mode))
1660                     m_state.setFoundConstants(true);
1661                 forNode(node) = result;
1662                 break;
1663             }
1664         }
1665
1666         clobberWorld(node->origin.semantic, clobberLimit);
1667         forNode(node).makeHeapTop();
1668         break;
1669     }
1670             
1671     case GetArrayLength: {
1672         JSArrayBufferView* view = m_graph.tryGetFoldableView(
1673             forNode(node->child1()).m_value, node->arrayMode());
1674         if (view) {
1675             setConstant(node, jsNumber(view->length()));
1676             break;
1677         }
1678         forNode(node).setType(SpecInt32);
1679         break;
1680     }
1681         
1682     case CheckStructure: {
1683         AbstractValue& value = forNode(node->child1());
1684         ASSERT(!(value.m_type & ~SpecCell)); // Edge filtering should have already ensured this.
1685
1686         StructureSet& set = node->structureSet();
1687         
1688         // It's interesting that we could have proven that the object has a larger structure set
1689         // that includes the set we're testing. In that case we could make the structure check
1690         // more efficient. We currently don't.
1691         
1692         if (value.m_structure.isSubsetOf(set)) {
1693             m_state.setFoundConstants(true);
1694             break;
1695         }
1696
1697         filter(value, set);
1698         break;
1699     }
1700         
1701     case CheckStructureImmediate: {
1702         // FIXME: This currently can only reason about one structure at a time.
1703         // https://bugs.webkit.org/show_bug.cgi?id=136988
1704         
1705         AbstractValue& value = forNode(node->child1());
1706         StructureSet& set = node->structureSet();
1707         
1708         if (value.value()) {
1709             if (Structure* structure = jsDynamicCast<Structure*>(value.value())) {
1710                 if (set.contains(structure)) {
1711                     m_state.setFoundConstants(true);
1712                     break;
1713                 }
1714             }
1715             m_state.setIsValid(false);
1716             break;
1717         }
1718         
1719         if (m_phiChildren) {
1720             bool allGood = true;
1721             m_phiChildren->forAllTransitiveIncomingValues(
1722                 node,
1723                 [&] (Node* incoming) {
1724                     if (Structure* structure = incoming->dynamicCastConstant<Structure*>()) {
1725                         if (set.contains(structure))
1726                             return;
1727                     }
1728                     allGood = false;
1729                 });
1730             if (allGood) {
1731                 m_state.setFoundConstants(true);
1732                 break;
1733             }
1734         }
1735             
1736         if (Structure* structure = set.onlyStructure()) {
1737             filterByValue(node->child1(), *m_graph.freeze(structure));
1738             break;
1739         }
1740         
1741         // Aw shucks, we can't do anything!
1742         break;
1743     }
1744         
1745     case PutStructure:
1746         if (!forNode(node->child1()).m_structure.isClear()) {
1747             if (forNode(node->child1()).m_structure.onlyStructure() == node->transition()->next)
1748                 m_state.setFoundConstants(true);
1749             else {
1750                 observeTransition(
1751                     clobberLimit, node->transition()->previous, node->transition()->next);
1752                 forNode(node->child1()).changeStructure(m_graph, node->transition()->next);
1753             }
1754         }
1755         break;
1756     case GetButterfly:
1757     case AllocatePropertyStorage:
1758     case ReallocatePropertyStorage:
1759         forNode(node).clear(); // The result is not a JS value.
1760         break;
1761     case CheckArray: {
1762         if (node->arrayMode().alreadyChecked(m_graph, node, forNode(node->child1()))) {
1763             m_state.setFoundConstants(true);
1764             break;
1765         }
1766         switch (node->arrayMode().type()) {
1767         case Array::String:
1768             filter(node->child1(), SpecString);
1769             break;
1770         case Array::Int32:
1771         case Array::Double:
1772         case Array::Contiguous:
1773         case Array::ArrayStorage:
1774         case Array::SlowPutArrayStorage:
1775             break;
1776         case Array::DirectArguments:
1777             filter(node->child1(), SpecDirectArguments);
1778             break;
1779         case Array::ScopedArguments:
1780             filter(node->child1(), SpecScopedArguments);
1781             break;
1782         case Array::Int8Array:
1783             filter(node->child1(), SpecInt8Array);
1784             break;
1785         case Array::Int16Array:
1786             filter(node->child1(), SpecInt16Array);
1787             break;
1788         case Array::Int32Array:
1789             filter(node->child1(), SpecInt32Array);
1790             break;
1791         case Array::Uint8Array:
1792             filter(node->child1(), SpecUint8Array);
1793             break;
1794         case Array::Uint8ClampedArray:
1795             filter(node->child1(), SpecUint8ClampedArray);
1796             break;
1797         case Array::Uint16Array:
1798             filter(node->child1(), SpecUint16Array);
1799             break;
1800         case Array::Uint32Array:
1801             filter(node->child1(), SpecUint32Array);
1802             break;
1803         case Array::Float32Array:
1804             filter(node->child1(), SpecFloat32Array);
1805             break;
1806         case Array::Float64Array:
1807             filter(node->child1(), SpecFloat64Array);
1808             break;
1809         default:
1810             RELEASE_ASSERT_NOT_REACHED();
1811             break;
1812         }
1813         filterArrayModes(node->child1(), node->arrayMode().arrayModesThatPassFiltering());
1814         break;
1815     }
1816     case Arrayify: {
1817         if (node->arrayMode().alreadyChecked(m_graph, node, forNode(node->child1()))) {
1818             m_state.setFoundConstants(true);
1819             break;
1820         }
1821         ASSERT(node->arrayMode().conversion() == Array::Convert);
1822         clobberStructures(clobberLimit);
1823         filterArrayModes(node->child1(), node->arrayMode().arrayModesThatPassFiltering());
1824         break;
1825     }
1826     case ArrayifyToStructure: {
1827         AbstractValue& value = forNode(node->child1());
1828         if (value.m_structure.isSubsetOf(StructureSet(node->structure())))
1829             m_state.setFoundConstants(true);
1830         clobberStructures(clobberLimit);
1831         
1832         // We have a bunch of options of how to express the abstract set at this point. Let set S
1833         // be the set of structures that the value had before clobbering and assume that all of
1834         // them are watchable. The new value should be the least expressible upper bound of the
1835         // intersection of "values that currently have structure = node->structure()" and "values
1836         // that have structure in S plus any structure transition-reachable from S". Assume that
1837         // node->structure() is not in S but it is transition-reachable from S. Then we would
1838         // like to say that the result is "values that have structure = node->structure() until
1839         // we invalidate", but there is no way to express this using the AbstractValue syntax. So
1840         // we must choose between:
1841         //
1842         // 1) "values that currently have structure = node->structure()". This is a valid
1843         //    superset of the value that we really want, and it's specific enough to satisfy the
1844         //    preconditions of the array access that this is guarding. It's also specific enough
1845         //    to allow relevant optimizations in the case that we didn't have a contradiction
1846         //    like in this example. Notice that in the abscence of any contradiction, this result
1847         //    is precise rather than being a conservative LUB.
1848         //
1849         // 2) "values that currently hava structure in S plus any structure transition-reachable
1850         //    from S". This is also a valid superset of the value that we really want, but it's
1851         //    not specific enough to satisfy the preconditions of the array access that this is
1852         //    guarding - so playing such shenanigans would preclude us from having assertions on
1853         //    the typing preconditions of any array accesses. This would also not be a desirable
1854         //    answer in the absence of a contradiction.
1855         //
1856         // Note that it's tempting to simply say that the resulting value is BOTTOM because of
1857         // the contradiction. That would be wrong, since we haven't hit an invalidation point,
1858         // yet.
1859         value.set(m_graph, node->structure());
1860         break;
1861     }
1862     case GetIndexedPropertyStorage: {
1863         JSArrayBufferView* view = m_graph.tryGetFoldableView(
1864             forNode(node->child1()).m_value, node->arrayMode());
1865         if (view)
1866             m_state.setFoundConstants(true);
1867         forNode(node).clear();
1868         break;
1869     }
1870     case ConstantStoragePointer: {
1871         forNode(node).clear();
1872         break; 
1873     }
1874         
1875     case GetTypedArrayByteOffset: {
1876         JSArrayBufferView* view = m_graph.tryGetFoldableView(forNode(node->child1()).m_value);
1877         if (view) {
1878             setConstant(node, jsNumber(view->byteOffset()));
1879             break;
1880         }
1881         forNode(node).setType(SpecInt32);
1882         break;
1883     }
1884         
1885     case GetByOffset: {
1886         StorageAccessData& data = node->storageAccessData();
1887         JSValue result = m_graph.tryGetConstantProperty(forNode(node->child2()), data.offset);
1888         if (result) {
1889             setConstant(node, *m_graph.freeze(result));
1890             break;
1891         }
1892         
1893         forNode(node).makeHeapTop();
1894         break;
1895     }
1896         
1897     case GetGetterSetterByOffset: {
1898         StorageAccessData& data = node->storageAccessData();
1899         JSValue result = m_graph.tryGetConstantProperty(forNode(node->child2()), data.offset);
1900         if (result && jsDynamicCast<GetterSetter*>(result)) {
1901             setConstant(node, *m_graph.freeze(result));
1902             break;
1903         }
1904         
1905         forNode(node).set(m_graph, m_graph.m_vm.getterSetterStructure.get());
1906         break;
1907     }
1908         
1909     case MultiGetByOffset: {
1910         // This code will filter the base value in a manner that is possibly different (either more
1911         // or less precise) than the way it would be filtered if this was strength-reduced to a
1912         // CheckStructure. This is fine. It's legal for different passes over the code to prove
1913         // different things about the code, so long as all of them are sound. That even includes
1914         // one guy proving that code should never execute (due to a contradiction) and another guy
1915         // not finding that contradiction. If someone ever proved that there would be a
1916         // contradiction then there must always be a contradiction even if subsequent passes don't
1917         // realize it. This is the case here.
1918         
1919         // Ordinarily you have to be careful with calling setFoundConstants()
1920         // because of the effect on compile times, but this node is FTL-only.
1921         m_state.setFoundConstants(true);
1922         
1923         AbstractValue base = forNode(node->child1());
1924         StructureSet baseSet;
1925         AbstractValue result;
1926         for (unsigned i = node->multiGetByOffsetData().variants.size(); i--;) {
1927             GetByIdVariant& variant = node->multiGetByOffsetData().variants[i];
1928             StructureSet set = variant.structureSet();
1929             set.filter(base);
1930             if (set.isEmpty())
1931                 continue;
1932             baseSet.merge(set);
1933             
1934             JSValue baseForLoad;
1935             if (variant.alternateBase())
1936                 baseForLoad = variant.alternateBase();
1937             else
1938                 baseForLoad = base.m_value;
1939             JSValue constantResult =
1940                 m_graph.tryGetConstantProperty(
1941                     baseForLoad, variant.baseStructure(), variant.offset());
1942             if (!constantResult) {
1943                 result.makeHeapTop();
1944                 continue;
1945             }
1946             AbstractValue thisResult;
1947             thisResult.set(
1948                 m_graph,
1949                 *m_graph.freeze(constantResult),
1950                 m_state.structureClobberState());
1951             result.merge(thisResult);
1952         }
1953         
1954         if (forNode(node->child1()).changeStructure(m_graph, baseSet) == Contradiction)
1955             m_state.setIsValid(false);
1956         
1957         forNode(node) = result;
1958         break;
1959     }
1960             
1961     case PutByOffset: {
1962         break;
1963     }
1964         
1965     case MultiPutByOffset: {
1966         StructureSet newSet;
1967         TransitionVector transitions;
1968         
1969         // Ordinarily you have to be careful with calling setFoundConstants()
1970         // because of the effect on compile times, but this node is FTL-only.
1971         m_state.setFoundConstants(true);
1972         
1973         AbstractValue base = forNode(node->child1());
1974         
1975         for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
1976             const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
1977             StructureSet thisSet = variant.oldStructure();
1978             thisSet.filter(base);
1979             if (thisSet.isEmpty())
1980                 continue;
1981             if (variant.kind() == PutByIdVariant::Transition) {
1982                 if (thisSet.onlyStructure() != variant.newStructure()) {
1983                     transitions.append(
1984                         Transition(variant.oldStructureForTransition(), variant.newStructure()));
1985                 } // else this is really a replace.
1986                 newSet.add(variant.newStructure());
1987             } else {
1988                 ASSERT(variant.kind() == PutByIdVariant::Replace);
1989                 newSet.merge(thisSet);
1990             }
1991         }
1992         
1993         observeTransitions(clobberLimit, transitions);
1994         if (forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction)
1995             m_state.setIsValid(false);
1996         break;
1997     }
1998         
1999     case GetExecutable: {
2000         JSValue value = forNode(node->child1()).value();
2001         if (value) {
2002             JSFunction* function = jsDynamicCast<JSFunction*>(value);
2003             if (function) {
2004                 setConstant(node, *m_graph.freeze(function->executable()));
2005                 break;
2006             }
2007         }
2008         forNode(node).setType(m_graph, SpecCellOther);
2009         break;
2010     }
2011     
2012     case CheckCell: {
2013         JSValue value = forNode(node->child1()).value();
2014         if (value == node->cellOperand()->value()) {
2015             m_state.setFoundConstants(true);
2016             ASSERT(value);
2017             break;
2018         }
2019         filterByValue(node->child1(), *node->cellOperand());
2020         break;
2021     }
2022
2023     case CheckNotEmpty: {
2024         AbstractValue& value = forNode(node->child1());
2025         if (!(value.m_type & SpecEmpty)) {
2026             m_state.setFoundConstants(true);
2027             break;
2028         }
2029         
2030         filter(value, ~SpecEmpty);
2031         break;
2032     }
2033
2034     case CheckInBounds: {
2035         JSValue left = forNode(node->child1()).value();
2036         JSValue right = forNode(node->child2()).value();
2037         if (left && right && left.isInt32() && right.isInt32()
2038             && static_cast<uint32_t>(left.asInt32()) < static_cast<uint32_t>(right.asInt32())) {
2039             m_state.setFoundConstants(true);
2040             break;
2041         }
2042         break;
2043     }
2044         
2045     case PutById:
2046     case PutByIdFlush:
2047     case PutByIdDirect: {
2048         AbstractValue& value = forNode(node->child1());
2049         if (!value.m_structure.isTop() && !value.m_structure.isClobbered()) {
2050             PutByIdStatus status = PutByIdStatus::computeFor(
2051                 m_graph.globalObjectFor(node->origin.semantic),
2052                 value.m_structure.set(),
2053                 m_graph.identifiers()[node->identifierNumber()],
2054                 node->op() == PutByIdDirect);
2055             
2056             if (status.isSimple()) {
2057                 StructureSet newSet;
2058                 TransitionVector transitions;
2059                 
2060                 for (unsigned i = status.numVariants(); i--;) {
2061                     const PutByIdVariant& variant = status[i];
2062                     if (variant.kind() == PutByIdVariant::Transition) {
2063                         transitions.append(
2064                             Transition(
2065                                 variant.oldStructureForTransition(), variant.newStructure()));
2066                         m_graph.registerStructure(variant.newStructure());
2067                         newSet.add(variant.newStructure());
2068                     } else {
2069                         ASSERT(variant.kind() == PutByIdVariant::Replace);
2070                         newSet.merge(variant.oldStructure());
2071                     }
2072                 }
2073                 
2074                 if (status.numVariants() == 1 || isFTL(m_graph.m_plan.mode))
2075                     m_state.setFoundConstants(true);
2076                 
2077                 observeTransitions(clobberLimit, transitions);
2078                 if (forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction)
2079                     m_state.setIsValid(false);
2080                 break;
2081             }
2082         }
2083         
2084         clobberWorld(node->origin.semantic, clobberLimit);
2085         break;
2086     }
2087         
2088     case In: {
2089         // FIXME: We can determine when the property definitely exists based on abstract
2090         // value information.
2091         clobberWorld(node->origin.semantic, clobberLimit);
2092         forNode(node).setType(SpecBoolean);
2093         break;
2094     }
2095             
2096     case GetEnumerableLength: {
2097         forNode(node).setType(SpecInt32);
2098         break;
2099     }
2100     case HasGenericProperty: {
2101         forNode(node).setType(SpecBoolean);
2102         break;
2103     }
2104     case HasStructureProperty: {
2105         forNode(node).setType(SpecBoolean);
2106         break;
2107     }
2108     case HasIndexedProperty: {
2109         ArrayMode mode = node->arrayMode();
2110         switch (mode.type()) {
2111         case Array::Int32:
2112         case Array::Double:
2113         case Array::Contiguous:
2114         case Array::ArrayStorage: {
2115             break;
2116         }
2117         default: {
2118             clobberWorld(node->origin.semantic, clobberLimit);
2119             break;
2120         }
2121         }
2122         forNode(node).setType(SpecBoolean);
2123         break;
2124     }
2125     case GetDirectPname: {
2126         clobberWorld(node->origin.semantic, clobberLimit);
2127         forNode(node).makeHeapTop();
2128         break;
2129     }
2130     case GetPropertyEnumerator: {
2131         forNode(node).setType(m_graph, SpecCell);
2132         break;
2133     }
2134     case GetEnumeratorStructurePname: {
2135         forNode(node).setType(m_graph, SpecString | SpecOther);
2136         break;
2137     }
2138     case GetEnumeratorGenericPname: {
2139         forNode(node).setType(m_graph, SpecString | SpecOther);
2140         break;
2141     }
2142     case ToIndexString: {
2143         forNode(node).setType(m_graph, SpecString);
2144         break;
2145     }
2146
2147     case GetGlobalVar:
2148         forNode(node).makeHeapTop();
2149         break;
2150         
2151     case VarInjectionWatchpoint:
2152     case PutGlobalVar:
2153     case NotifyWrite:
2154         break;
2155             
2156     case CheckHasInstance:
2157         // Sadly, we don't propagate the fact that we've done CheckHasInstance
2158         break;
2159             
2160     case InstanceOf:
2161         // Again, sadly, we don't propagate the fact that we've done InstanceOf
2162         forNode(node).setType(SpecBoolean);
2163         break;
2164             
2165     case Phi:
2166         RELEASE_ASSERT(m_graph.m_form == SSA);
2167         // The state of this node would have already been decided, but it may have become a
2168         // constant, in which case we'd like to know.
2169         if (forNode(node).m_value)
2170             m_state.setFoundConstants(true);
2171         break;
2172         
2173     case Upsilon: {
2174         m_state.createValueForNode(node->phi());
2175         forNode(node->phi()) = forNode(node->child1());
2176         break;
2177     }
2178         
2179     case Flush:
2180     case PhantomLocal:
2181         break;
2182             
2183     case Call:
2184     case Construct:
2185     case NativeCall:
2186     case NativeConstruct:
2187     case CallVarargs:
2188     case CallForwardVarargs:
2189     case ConstructVarargs:
2190     case ConstructForwardVarargs:
2191         clobberWorld(node->origin.semantic, clobberLimit);
2192         forNode(node).makeHeapTop();
2193         break;
2194
2195     case ForceOSRExit:
2196     case CheckBadCell:
2197         m_state.setIsValid(false);
2198         break;
2199         
2200     case InvalidationPoint:
2201         forAllValues(clobberLimit, AbstractValue::observeInvalidationPointFor);
2202         m_state.setStructureClobberState(StructuresAreWatched);
2203         break;
2204
2205     case CheckWatchdogTimer:
2206         break;
2207
2208     case Breakpoint:
2209     case ProfileWillCall:
2210     case ProfileDidCall:
2211     case ProfileType:
2212     case ProfileControlFlow:
2213     case Phantom:
2214     case CountExecution:
2215     case CheckTierUpInLoop:
2216     case CheckTierUpAtReturn:
2217         break;
2218
2219     case Check: {
2220         // Simplify out checks that don't actually do checking.
2221         for (unsigned i = 0; i < AdjacencyList::Size; ++i) {
2222             Edge edge = node->children.child(i);
2223             if (!edge)
2224                 break;
2225             if (edge.isProved() || edge.willNotHaveCheck()) {
2226                 m_state.setFoundConstants(true);
2227                 break;
2228             }
2229         }
2230         break;
2231     }
2232
2233     case StoreBarrier: {
2234         filter(node->child1(), SpecCell);
2235         break;
2236     }
2237
2238     case StoreBarrierWithNullCheck: {
2239         break;
2240     }
2241
2242     case CheckTierUpAndOSREnter:
2243     case LoopHint:
2244     case ZombieHint:
2245         break;
2246
2247     case Unreachable:
2248     case LastNodeType:
2249     case ArithIMul:
2250     case FiatInt52:
2251         DFG_CRASH(m_graph, node, "Unexpected node type");
2252         break;
2253     }
2254     
2255     return m_state.isValid();
2256 }
2257
2258 template<typename AbstractStateType>
2259 bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned indexInBlock)
2260 {
2261     return executeEffects(indexInBlock, m_state.block()->at(indexInBlock));
2262 }
2263
2264 template<typename AbstractStateType>
2265 bool AbstractInterpreter<AbstractStateType>::execute(unsigned indexInBlock)
2266 {
2267     Node* node = m_state.block()->at(indexInBlock);
2268     
2269     startExecuting();
2270     executeEdges(node);
2271     return executeEffects(indexInBlock, node);
2272 }
2273
2274 template<typename AbstractStateType>
2275 bool AbstractInterpreter<AbstractStateType>::execute(Node* node)
2276 {
2277     startExecuting();
2278     executeEdges(node);
2279     return executeEffects(UINT_MAX, node);
2280 }
2281
2282 template<typename AbstractStateType>
2283 void AbstractInterpreter<AbstractStateType>::clobberWorld(
2284     const CodeOrigin&, unsigned clobberLimit)
2285 {
2286     clobberStructures(clobberLimit);
2287 }
2288
2289 template<typename AbstractStateType>
2290 template<typename Functor>
2291 void AbstractInterpreter<AbstractStateType>::forAllValues(
2292     unsigned clobberLimit, Functor& functor)
2293 {
2294     SamplingRegion samplingRegion("DFG AI For All Values");
2295     if (clobberLimit >= m_state.block()->size())
2296         clobberLimit = m_state.block()->size();
2297     else
2298         clobberLimit++;
2299     ASSERT(clobberLimit <= m_state.block()->size());
2300     for (size_t i = clobberLimit; i--;)
2301         functor(forNode(m_state.block()->at(i)));
2302     if (m_graph.m_form == SSA) {
2303         HashSet<Node*>::iterator iter = m_state.block()->ssa->liveAtHead.begin();
2304         HashSet<Node*>::iterator end = m_state.block()->ssa->liveAtHead.end();
2305         for (; iter != end; ++iter)
2306             functor(forNode(*iter));
2307     }
2308     for (size_t i = m_state.variables().numberOfArguments(); i--;)
2309         functor(m_state.variables().argument(i));
2310     for (size_t i = m_state.variables().numberOfLocals(); i--;)
2311         functor(m_state.variables().local(i));
2312 }
2313
2314 template<typename AbstractStateType>
2315 void AbstractInterpreter<AbstractStateType>::clobberStructures(unsigned clobberLimit)
2316 {
2317     SamplingRegion samplingRegion("DFG AI Clobber Structures");
2318     forAllValues(clobberLimit, AbstractValue::clobberStructuresFor);
2319     setDidClobber();
2320 }
2321
2322 template<typename AbstractStateType>
2323 void AbstractInterpreter<AbstractStateType>::observeTransition(
2324     unsigned clobberLimit, Structure* from, Structure* to)
2325 {
2326     AbstractValue::TransitionObserver transitionObserver(from, to);
2327     forAllValues(clobberLimit, transitionObserver);
2328     
2329     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.
2330 }
2331
2332 template<typename AbstractStateType>
2333 void AbstractInterpreter<AbstractStateType>::observeTransitions(
2334     unsigned clobberLimit, const TransitionVector& vector)
2335 {
2336     AbstractValue::TransitionsObserver transitionsObserver(vector);
2337     forAllValues(clobberLimit, transitionsObserver);
2338     
2339     if (!ASSERT_DISABLED) {
2340         // We don't need to claim to be in a clobbered state because none of the Transition::previous structures are watchable.
2341         for (unsigned i = vector.size(); i--;)
2342             ASSERT(!vector[i].previous->dfgShouldWatch());
2343     }
2344 }
2345
2346 template<typename AbstractStateType>
2347 void AbstractInterpreter<AbstractStateType>::setDidClobber()
2348 {
2349     m_state.setDidClobber(true);
2350     m_state.setStructureClobberState(StructuresAreClobbered);
2351 }
2352
2353 template<typename AbstractStateType>
2354 void AbstractInterpreter<AbstractStateType>::dump(PrintStream& out) const
2355 {
2356     const_cast<AbstractInterpreter<AbstractStateType>*>(this)->dump(out);
2357 }
2358
2359 template<typename AbstractStateType>
2360 void AbstractInterpreter<AbstractStateType>::dump(PrintStream& out)
2361 {
2362     CommaPrinter comma(" ");
2363     HashSet<Node*> seen;
2364     if (m_graph.m_form == SSA) {
2365         HashSet<Node*>::iterator iter = m_state.block()->ssa->liveAtHead.begin();
2366         HashSet<Node*>::iterator end = m_state.block()->ssa->liveAtHead.end();
2367         for (; iter != end; ++iter) {
2368             Node* node = *iter;
2369             seen.add(node);
2370             AbstractValue& value = forNode(node);
2371             if (value.isClear())
2372                 continue;
2373             out.print(comma, node, ":", value);
2374         }
2375     }
2376     for (size_t i = 0; i < m_state.block()->size(); ++i) {
2377         Node* node = m_state.block()->at(i);
2378         seen.add(node);
2379         AbstractValue& value = forNode(node);
2380         if (value.isClear())
2381             continue;
2382         out.print(comma, node, ":", value);
2383     }
2384     if (m_graph.m_form == SSA) {
2385         HashSet<Node*>::iterator iter = m_state.block()->ssa->liveAtTail.begin();
2386         HashSet<Node*>::iterator end = m_state.block()->ssa->liveAtTail.end();
2387         for (; iter != end; ++iter) {
2388             Node* node = *iter;
2389             if (seen.contains(node))
2390                 continue;
2391             AbstractValue& value = forNode(node);
2392             if (value.isClear())
2393                 continue;
2394             out.print(comma, node, ":", value);
2395         }
2396     }
2397 }
2398
2399 template<typename AbstractStateType>
2400 FiltrationResult AbstractInterpreter<AbstractStateType>::filter(
2401     AbstractValue& value, const StructureSet& set)
2402 {
2403     if (value.filter(m_graph, set) == FiltrationOK)
2404         return FiltrationOK;
2405     m_state.setIsValid(false);
2406     return Contradiction;
2407 }
2408
2409 template<typename AbstractStateType>
2410 FiltrationResult AbstractInterpreter<AbstractStateType>::filterArrayModes(
2411     AbstractValue& value, ArrayModes arrayModes)
2412 {
2413     if (value.filterArrayModes(arrayModes) == FiltrationOK)
2414         return FiltrationOK;
2415     m_state.setIsValid(false);
2416     return Contradiction;
2417 }
2418
2419 template<typename AbstractStateType>
2420 FiltrationResult AbstractInterpreter<AbstractStateType>::filter(
2421     AbstractValue& value, SpeculatedType type)
2422 {
2423     if (value.filter(type) == FiltrationOK)
2424         return FiltrationOK;
2425     m_state.setIsValid(false);
2426     return Contradiction;
2427 }
2428
2429 template<typename AbstractStateType>
2430 FiltrationResult AbstractInterpreter<AbstractStateType>::filterByValue(
2431     AbstractValue& abstractValue, FrozenValue concreteValue)
2432 {
2433     if (abstractValue.filterByValue(concreteValue) == FiltrationOK)
2434         return FiltrationOK;
2435     m_state.setIsValid(false);
2436     return Contradiction;
2437 }
2438
2439 } } // namespace JSC::DFG
2440
2441 #endif // ENABLE(DFG_JIT)
2442
2443 #endif // DFGAbstractInterpreterInlines_h
2444