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