fourthTier: DFG shouldn't create CheckStructures for array accesses except if the...
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGAbstractInterpreterInlines.h
1 /*
2  * Copyright (C) 2013 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 #include <wtf/Platform.h>
30
31 #if ENABLE(DFG_JIT)
32
33 #include "DFGAbstractInterpreter.h"
34 #include "GetByIdStatus.h"
35 #include "Operations.h"
36 #include "PutByIdStatus.h"
37 #include "StringObject.h"
38
39 namespace JSC { namespace DFG {
40
41 template<typename AbstractStateType>
42 AbstractInterpreter<AbstractStateType>::AbstractInterpreter(Graph& graph, AbstractStateType& state)
43     : m_codeBlock(graph.m_codeBlock)
44     , m_graph(graph)
45     , m_state(state)
46 {
47 }
48
49 template<typename AbstractStateType>
50 AbstractInterpreter<AbstractStateType>::~AbstractInterpreter()
51 {
52 }
53
54 template<typename AbstractStateType>
55 typename AbstractInterpreter<AbstractStateType>::BooleanResult
56 AbstractInterpreter<AbstractStateType>::booleanResult(
57     Node* node, AbstractValue& value)
58 {
59     JSValue childConst = value.value();
60     if (childConst) {
61         if (childConst.toBoolean(m_codeBlock->globalObjectFor(node->codeOrigin)->globalExec()))
62             return DefinitelyTrue;
63         return DefinitelyFalse;
64     }
65
66     // Next check if we can fold because we know that the source is an object or string and does not equal undefined.
67     if (isCellSpeculation(value.m_type)
68         && value.m_currentKnownStructure.hasSingleton()) {
69         Structure* structure = value.m_currentKnownStructure.singleton();
70         if (!structure->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node->codeOrigin))
71             && structure->typeInfo().type() != StringType)
72             return DefinitelyTrue;
73     }
74     
75     return UnknownBooleanResult;
76 }
77
78 template<typename AbstractStateType>
79 bool AbstractInterpreter<AbstractStateType>::startExecuting(Node* node)
80 {
81     ASSERT(m_state.block());
82     ASSERT(m_state.isValid());
83     
84     m_state.setDidClobber(false);
85     
86     node->setCanExit(false);
87     
88     return node->shouldGenerate();
89 }
90
91 template<typename AbstractStateType>
92 bool AbstractInterpreter<AbstractStateType>::startExecuting(unsigned indexInBlock)
93 {
94     return startExecuting(m_state.block()->at(indexInBlock));
95 }
96
97 template<typename AbstractStateType>
98 void AbstractInterpreter<AbstractStateType>::executeEdges(Node* node)
99 {
100     DFG_NODE_DO_TO_CHILDREN(m_graph, node, filterEdgeByUse);
101 }
102
103 template<typename AbstractStateType>
104 void AbstractInterpreter<AbstractStateType>::executeEdges(unsigned indexInBlock)
105 {
106     executeEdges(m_state.block()->at(indexInBlock));
107 }
108
109 template<typename AbstractStateType>
110 void AbstractInterpreter<AbstractStateType>::verifyEdge(Node*, Edge edge)
111 {
112     RELEASE_ASSERT(!(forNode(edge).m_type & ~typeFilterFor(edge.useKind())));
113 }
114
115 template<typename AbstractStateType>
116 void AbstractInterpreter<AbstractStateType>::verifyEdges(Node* node)
117 {
118     DFG_NODE_DO_TO_CHILDREN(m_graph, node, verifyEdge);
119 }
120
121 template<typename AbstractStateType>
122 bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned indexInBlock, Node* node)
123 {
124     if (!ASSERT_DISABLED)
125         verifyEdges(node);
126     
127     switch (node->op()) {
128     case JSConstant:
129     case WeakJSConstant:
130     case PhantomArguments: {
131         forNode(node).set(m_graph, m_graph.valueOfJSConstant(node));
132         break;
133     }
134         
135     case Identity: {
136         forNode(node) = forNode(node->child1());
137         break;
138     }
139         
140     case GetArgument: {
141         ASSERT(m_graph.m_form == SSA);
142         VariableAccessData* variable = node->variableAccessData();
143         AbstractValue& value = m_state.variables().operand(variable->local());
144         ASSERT(value.isTop());
145         FiltrationResult result =
146             value.filter(typeFilterFor(useKindFor(variable->flushFormat())));
147         ASSERT_UNUSED(result, result == FiltrationOK);
148         forNode(node) = value;
149         break;
150     }
151             
152     case GetLocal: {
153         VariableAccessData* variableAccessData = node->variableAccessData();
154         if (variableAccessData->prediction() == SpecNone) {
155             m_state.setIsValid(false);
156             break;
157         }
158         AbstractValue value = m_state.variables().operand(variableAccessData->local());
159         if (!variableAccessData->isCaptured()) {
160             if (value.isClear())
161                 node->setCanExit(true);
162         }
163         if (value.value())
164             m_state.setFoundConstants(true);
165         forNode(node) = value;
166         break;
167     }
168         
169     case GetLocalUnlinked: {
170         AbstractValue value = m_state.variables().operand(node->unlinkedLocal());
171         if (value.value())
172             m_state.setFoundConstants(true);
173         forNode(node) = value;
174         break;
175     }
176         
177     case SetLocal: {
178         m_state.variables().operand(node->local()) = forNode(node->child1());
179         break;
180     }
181         
182     case MovHint:
183     case MovHintAndCheck: {
184         // Don't need to do anything. A MovHint is effectively a promise that the SetLocal
185         // was dead.
186         break;
187     }
188         
189     case ZombieHint: {
190         RELEASE_ASSERT_NOT_REACHED();
191         break;
192     }
193             
194     case SetArgument:
195         // Assert that the state of arguments has been set.
196         ASSERT(!m_state.block()->valuesAtHead.operand(node->local()).isClear());
197         break;
198             
199     case BitAnd:
200     case BitOr:
201     case BitXor:
202     case BitRShift:
203     case BitLShift:
204     case BitURShift: {
205         JSValue left = forNode(node->child1()).value();
206         JSValue right = forNode(node->child2()).value();
207         if (left && right && left.isInt32() && right.isInt32()) {
208             int32_t a = left.asInt32();
209             int32_t b = right.asInt32();
210             bool constantWasSet;
211             switch (node->op()) {
212             case BitAnd:
213                 constantWasSet = trySetConstant(node, JSValue(a & b));
214                 break;
215             case BitOr:
216                 constantWasSet = trySetConstant(node, JSValue(a | b));
217                 break;
218             case BitXor:
219                 constantWasSet = trySetConstant(node, JSValue(a ^ b));
220                 break;
221             case BitRShift:
222                 constantWasSet = trySetConstant(node, JSValue(a >> static_cast<uint32_t>(b)));
223                 break;
224             case BitLShift:
225                 constantWasSet = trySetConstant(node, JSValue(a << static_cast<uint32_t>(b)));
226                 break;
227             case BitURShift:
228                 constantWasSet = trySetConstant(node, JSValue(static_cast<uint32_t>(a) >> static_cast<uint32_t>(b)));
229                 break;
230             default:
231                 RELEASE_ASSERT_NOT_REACHED();
232                 constantWasSet = false;
233             }
234             if (constantWasSet) {
235                 m_state.setFoundConstants(true);
236                 break;
237             }
238         }
239         forNode(node).setType(SpecInt32);
240         break;
241     }
242         
243     case UInt32ToNumber: {
244         JSValue child = forNode(node->child1()).value();
245         if (child && child.isNumber()) {
246             ASSERT(child.isInt32());
247             if (trySetConstant(node, JSValue(child.asUInt32()))) {
248                 m_state.setFoundConstants(true);
249                 break;
250             }
251         }
252         if (!node->canSpeculateInteger())
253             forNode(node).setType(SpecDouble);
254         else {
255             forNode(node).setType(SpecInt32);
256             node->setCanExit(true);
257         }
258         break;
259     }
260             
261     case DoubleAsInt32: {
262         JSValue child = forNode(node->child1()).value();
263         if (child && child.isNumber()) {
264             double asDouble = child.asNumber();
265             int32_t asInt = JSC::toInt32(asDouble);
266             if (bitwise_cast<int64_t>(static_cast<double>(asInt)) == bitwise_cast<int64_t>(asDouble)
267                 && trySetConstant(node, JSValue(asInt))) {
268                 m_state.setFoundConstants(true);
269                 break;
270             }
271         }
272         node->setCanExit(true);
273         forNode(node).setType(SpecInt32);
274         break;
275     }
276             
277     case ValueToInt32: {
278         JSValue child = forNode(node->child1()).value();
279         if (child && child.isNumber()) {
280             bool constantWasSet;
281             if (child.isInt32())
282                 constantWasSet = trySetConstant(node, child);
283             else
284                 constantWasSet = trySetConstant(node, JSValue(JSC::toInt32(child.asDouble())));
285             if (constantWasSet) {
286                 m_state.setFoundConstants(true);
287                 break;
288             }
289         }
290         
291         forNode(node).setType(SpecInt32);
292         break;
293     }
294
295     case Int32ToDouble:
296     case ForwardInt32ToDouble: {
297         JSValue child = forNode(node->child1()).value();
298         if (child && child.isNumber()
299             && trySetConstant(node, JSValue(JSValue::EncodeAsDouble, child.asNumber()))) {
300             m_state.setFoundConstants(true);
301             break;
302         }
303         if (isInt32Speculation(forNode(node->child1()).m_type))
304             forNode(node).setType(SpecDoubleReal);
305         else
306             forNode(node).setType(SpecDouble);
307         break;
308     }
309         
310     case ValueAdd:
311     case ArithAdd: {
312         JSValue left = forNode(node->child1()).value();
313         JSValue right = forNode(node->child2()).value();
314         if (left && right && left.isNumber() && right.isNumber()
315             && trySetConstant(node, JSValue(left.asNumber() + right.asNumber()))) {
316             m_state.setFoundConstants(true);
317             break;
318         }
319         switch (node->binaryUseKind()) {
320         case Int32Use:
321             forNode(node).setType(SpecInt32);
322             if (!nodeCanTruncateInteger(node->arithNodeFlags()))
323                 node->setCanExit(true);
324             break;
325         case NumberUse:
326             if (isRealNumberSpeculation(forNode(node->child1()).m_type)
327                 && isRealNumberSpeculation(forNode(node->child2()).m_type))
328                 forNode(node).setType(SpecDoubleReal);
329             else
330                 forNode(node).setType(SpecDouble);
331             break;
332         default:
333             RELEASE_ASSERT(node->op() == ValueAdd);
334             clobberWorld(node->codeOrigin, indexInBlock);
335             forNode(node).setType(SpecString | SpecInt32 | SpecNumber);
336             break;
337         }
338         break;
339     }
340         
341     case MakeRope: {
342         forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
343         break;
344     }
345             
346     case ArithSub: {
347         JSValue left = forNode(node->child1()).value();
348         JSValue right = forNode(node->child2()).value();
349         if (left && right && left.isNumber() && right.isNumber()
350             && trySetConstant(node, JSValue(left.asNumber() - right.asNumber()))) {
351             m_state.setFoundConstants(true);
352             break;
353         }
354         switch (node->binaryUseKind()) {
355         case Int32Use:
356             forNode(node).setType(SpecInt32);
357             if (!nodeCanTruncateInteger(node->arithNodeFlags()))
358                 node->setCanExit(true);
359             break;
360         case NumberUse:
361             forNode(node).setType(SpecDouble);
362             break;
363         default:
364             RELEASE_ASSERT_NOT_REACHED();
365             break;
366         }
367         break;
368     }
369         
370     case ArithNegate: {
371         JSValue child = forNode(node->child1()).value();
372         if (child && child.isNumber()
373             && trySetConstant(node, JSValue(-child.asNumber()))) {
374             m_state.setFoundConstants(true);
375             break;
376         }
377         switch (node->child1().useKind()) {
378         case Int32Use:
379             forNode(node).setType(SpecInt32);
380             if (!nodeCanTruncateInteger(node->arithNodeFlags()))
381                 node->setCanExit(true);
382             break;
383         case NumberUse:
384             forNode(node).setType(SpecDouble);
385             break;
386         default:
387             RELEASE_ASSERT_NOT_REACHED();
388             break;
389         }
390         break;
391     }
392         
393     case ArithMul: {
394         JSValue left = forNode(node->child1()).value();
395         JSValue right = forNode(node->child2()).value();
396         if (left && right && left.isNumber() && right.isNumber()
397             && trySetConstant(node, JSValue(left.asNumber() * right.asNumber()))) {
398             m_state.setFoundConstants(true);
399             break;
400         }
401         switch (node->binaryUseKind()) {
402         case Int32Use:
403             forNode(node).setType(SpecInt32);
404             if (!nodeCanTruncateInteger(node->arithNodeFlags())
405                 || !nodeCanIgnoreNegativeZero(node->arithNodeFlags()))
406                 node->setCanExit(true);
407             break;
408         case NumberUse:
409             if (isRealNumberSpeculation(forNode(node->child1()).m_type)
410                 || isRealNumberSpeculation(forNode(node->child2()).m_type))
411                 forNode(node).setType(SpecDoubleReal);
412             else
413                 forNode(node).setType(SpecDouble);
414             break;
415         default:
416             RELEASE_ASSERT_NOT_REACHED();
417             break;
418         }
419         break;
420     }
421
422     case ArithIMul: {
423         forNode(node).setType(SpecInt32);
424         break;
425     }
426         
427     case ArithDiv:
428     case ArithMin:
429     case ArithMax:
430     case ArithMod: {
431         JSValue left = forNode(node->child1()).value();
432         JSValue right = forNode(node->child2()).value();
433         if (node->op() == ArithMod && right && right.isNumber() && right.asNumber() == 1
434             && trySetConstant(node, JSValue(0))) {
435             m_state.setFoundConstants(true);
436             break;
437         }
438         if (left && right && left.isNumber() && right.isNumber()) {
439             double a = left.asNumber();
440             double b = right.asNumber();
441             bool constantWasSet;
442             switch (node->op()) {
443             case ArithDiv:
444                 constantWasSet = trySetConstant(node, JSValue(a / b));
445                 break;
446             case ArithMin:
447                 constantWasSet = trySetConstant(node, JSValue(a < b ? a : (b <= a ? b : a + b)));
448                 break;
449             case ArithMax:
450                 constantWasSet = trySetConstant(node, JSValue(a > b ? a : (b >= a ? b : a + b)));
451                 break;
452             case ArithMod:
453                 constantWasSet = trySetConstant(node, JSValue(fmod(a, b)));
454                 break;
455             default:
456                 RELEASE_ASSERT_NOT_REACHED();
457                 constantWasSet = false;
458                 break;
459             }
460             if (constantWasSet) {
461                 m_state.setFoundConstants(true);
462                 break;
463             }
464         }
465         switch (node->binaryUseKind()) {
466         case Int32Use:
467             forNode(node).setType(SpecInt32);
468             node->setCanExit(true);
469             break;
470         case NumberUse:
471             forNode(node).setType(SpecDouble);
472             break;
473         default:
474             RELEASE_ASSERT_NOT_REACHED();
475             break;
476         }
477         break;
478     }
479             
480     case ArithAbs: {
481         JSValue child = forNode(node->child1()).value();
482         if (child && child.isNumber()
483             && trySetConstant(node, JSValue(fabs(child.asNumber())))) {
484             m_state.setFoundConstants(true);
485             break;
486         }
487         switch (node->child1().useKind()) {
488         case Int32Use:
489             forNode(node).setType(SpecInt32);
490             node->setCanExit(true);
491             break;
492         case NumberUse:
493             forNode(node).setType(SpecDouble);
494             break;
495         default:
496             RELEASE_ASSERT_NOT_REACHED();
497             break;
498         }
499         break;
500     }
501             
502     case ArithSqrt: {
503         JSValue child = forNode(node->child1()).value();
504         if (child && child.isNumber()
505             && trySetConstant(node, JSValue(sqrt(child.asNumber())))) {
506             m_state.setFoundConstants(true);
507             break;
508         }
509         forNode(node).setType(SpecDouble);
510         break;
511     }
512             
513     case LogicalNot: {
514         bool didSetConstant = false;
515         switch (booleanResult(node, forNode(node->child1()))) {
516         case DefinitelyTrue:
517             didSetConstant = trySetConstant(node, jsBoolean(false));
518             break;
519         case DefinitelyFalse:
520             didSetConstant = trySetConstant(node, jsBoolean(true));
521             break;
522         default:
523             break;
524         }
525         if (didSetConstant) {
526             m_state.setFoundConstants(true);
527             break;
528         }
529         switch (node->child1().useKind()) {
530         case BooleanUse:
531         case Int32Use:
532         case NumberUse:
533         case UntypedUse:
534             break;
535         case ObjectOrOtherUse:
536             node->setCanExit(true);
537             break;
538         default:
539             RELEASE_ASSERT_NOT_REACHED();
540             break;
541         }
542         forNode(node).setType(SpecBoolean);
543         break;
544     }
545         
546     case IsUndefined:
547     case IsBoolean:
548     case IsNumber:
549     case IsString:
550     case IsObject:
551     case IsFunction: {
552         node->setCanExit(
553             node->op() == IsUndefined
554             && m_graph.masqueradesAsUndefinedWatchpointIsStillValid(node->codeOrigin));
555         JSValue child = forNode(node->child1()).value();
556         if (child) {
557             bool constantWasSet;
558             switch (node->op()) {
559             case IsUndefined:
560                 constantWasSet = trySetConstant(node, jsBoolean(
561                     child.isCell()
562                     ? child.asCell()->structure()->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node->codeOrigin))
563                     : child.isUndefined()));
564                 break;
565             case IsBoolean:
566                 constantWasSet = trySetConstant(node, jsBoolean(child.isBoolean()));
567                 break;
568             case IsNumber:
569                 constantWasSet = trySetConstant(node, jsBoolean(child.isNumber()));
570                 break;
571             case IsString:
572                 constantWasSet = trySetConstant(node, jsBoolean(isJSString(child)));
573                 break;
574             case IsObject:
575                 if (child.isNull() || !child.isObject()) {
576                     constantWasSet = trySetConstant(node, jsBoolean(child.isNull()));
577                     break;
578                 }
579             default:
580                 constantWasSet = false;
581                 break;
582             }
583             if (constantWasSet) {
584                 m_state.setFoundConstants(true);
585                 break;
586             }
587         }
588
589         forNode(node).setType(SpecBoolean);
590         break;
591     }
592
593     case TypeOf: {
594         VM* vm = m_codeBlock->vm();
595         JSValue child = forNode(node->child1()).value();
596         AbstractValue& abstractChild = forNode(node->child1());
597         if (child) {
598             JSValue typeString = jsTypeStringForValue(*vm, m_codeBlock->globalObjectFor(node->codeOrigin), child);
599             if (trySetConstant(node, typeString)) {
600                 m_state.setFoundConstants(true);
601                 break;
602             }
603         } else if (isNumberSpeculation(abstractChild.m_type)) {
604             if (trySetConstant(node, vm->smallStrings.numberString())) {
605                 filter(node->child1(), SpecNumber);
606                 m_state.setFoundConstants(true);
607                 break;
608             }
609         } else if (isStringSpeculation(abstractChild.m_type)) {
610             if (trySetConstant(node, vm->smallStrings.stringString())) {
611                 filter(node->child1(), SpecString);
612                 m_state.setFoundConstants(true);
613                 break;
614             }
615         } else if (isFinalObjectSpeculation(abstractChild.m_type) || isArraySpeculation(abstractChild.m_type) || isArgumentsSpeculation(abstractChild.m_type)) {
616             if (trySetConstant(node, vm->smallStrings.objectString())) {
617                 filter(node->child1(), SpecFinalObject | SpecArray | SpecArguments);
618                 m_state.setFoundConstants(true);
619                 break;
620             }
621         } else if (isFunctionSpeculation(abstractChild.m_type)) {
622             if (trySetConstant(node, vm->smallStrings.functionString())) {
623                 filter(node->child1(), SpecFunction);
624                 m_state.setFoundConstants(true);
625                 break;
626             }
627         } else if (isBooleanSpeculation(abstractChild.m_type)) {
628             if (trySetConstant(node, vm->smallStrings.booleanString())) {
629                 filter(node->child1(), SpecBoolean);
630                 m_state.setFoundConstants(true);
631                 break;
632             }
633         }
634
635         switch (node->child1().useKind()) {
636         case StringUse:
637         case CellUse:
638             node->setCanExit(true);
639             break;
640         case UntypedUse:
641             break;
642         default:
643             RELEASE_ASSERT_NOT_REACHED();
644             break;
645         }
646         forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
647         break;
648     }
649             
650     case CompareLess:
651     case CompareLessEq:
652     case CompareGreater:
653     case CompareGreaterEq:
654     case CompareEq:
655     case CompareEqConstant: {
656         bool constantWasSet = false;
657
658         JSValue leftConst = forNode(node->child1()).value();
659         JSValue rightConst = forNode(node->child2()).value();
660         if (leftConst && rightConst) {
661             if (leftConst.isNumber() && rightConst.isNumber()) {
662                 double a = leftConst.asNumber();
663                 double b = rightConst.asNumber();
664                 switch (node->op()) {
665                 case CompareLess:
666                     constantWasSet = trySetConstant(node, jsBoolean(a < b));
667                     break;
668                 case CompareLessEq:
669                     constantWasSet = trySetConstant(node, jsBoolean(a <= b));
670                     break;
671                 case CompareGreater:
672                     constantWasSet = trySetConstant(node, jsBoolean(a > b));
673                     break;
674                 case CompareGreaterEq:
675                     constantWasSet = trySetConstant(node, jsBoolean(a >= b));
676                     break;
677                 case CompareEq:
678                     constantWasSet = trySetConstant(node, jsBoolean(a == b));
679                     break;
680                 default:
681                     RELEASE_ASSERT_NOT_REACHED();
682                     constantWasSet = false;
683                     break;
684                 }
685             }
686             
687             if (!constantWasSet && node->op() == CompareEq
688                 && leftConst.isString() && rightConst.isString()) {
689                 const StringImpl* a = asString(leftConst)->tryGetValueImpl();
690                 const StringImpl* b = asString(rightConst)->tryGetValueImpl();
691                 if (a && b)
692                     constantWasSet = trySetConstant(node, jsBoolean(WTF::equal(a, b)));
693             }
694         }
695         
696         if (!constantWasSet && (node->op() == CompareEqConstant || node->op() == CompareEq)) {
697             SpeculatedType leftType = forNode(node->child1()).m_type;
698             SpeculatedType rightType = forNode(node->child2()).m_type;
699             if ((isInt32Speculation(leftType) && isOtherSpeculation(rightType))
700                 || (isOtherSpeculation(leftType) && isInt32Speculation(rightType)))
701                 constantWasSet = trySetConstant(node, jsBoolean(false));
702         }
703         
704         if (constantWasSet) {
705             m_state.setFoundConstants(true);
706             break;
707         }
708         
709         forNode(node).setType(SpecBoolean);
710         
711         // This is overly conservative. But the only thing this prevents is store elimination,
712         // and how likely is it, really, that you'll have redundant stores across a comparison
713         // operation? Comparison operations are typically at the end of basic blocks, so
714         // unless we have global store elimination (super unlikely given how unprofitable that
715         // optimization is to begin with), you aren't going to be wanting to store eliminate
716         // across an equality op.
717         node->setCanExit(true);
718         break;
719     }
720             
721     case CompareStrictEq:
722     case CompareStrictEqConstant: {
723         Node* leftNode = node->child1().node();
724         Node* rightNode = node->child2().node();
725         JSValue left = forNode(leftNode).value();
726         JSValue right = forNode(rightNode).value();
727         if (left && right) {
728             if (left.isNumber() && right.isNumber()
729                 && trySetConstant(node, jsBoolean(left.asNumber() == right.asNumber()))) {
730                 m_state.setFoundConstants(true);
731                 break;
732             }
733             if (left.isString() && right.isString()) {
734                 const StringImpl* a = asString(left)->tryGetValueImpl();
735                 const StringImpl* b = asString(right)->tryGetValueImpl();
736                 if (a && b && trySetConstant(node, jsBoolean(WTF::equal(a, b)))) {
737                     m_state.setFoundConstants(true);
738                     break;
739                 }
740             }
741         }
742         forNode(node).setType(SpecBoolean);
743         node->setCanExit(true); // This is overly conservative.
744         break;
745     }
746         
747     case StringCharCodeAt:
748         node->setCanExit(true);
749         forNode(node).setType(SpecInt32);
750         break;
751         
752     case StringFromCharCode:
753         forNode(node).setType(SpecString);
754         break;
755
756     case StringCharAt:
757         node->setCanExit(true);
758         forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
759         break;
760             
761     case GetByVal: {
762         node->setCanExit(true);
763         switch (node->arrayMode().type()) {
764         case Array::SelectUsingPredictions:
765         case Array::Unprofiled:
766         case Array::Undecided:
767             RELEASE_ASSERT_NOT_REACHED();
768             break;
769         case Array::ForceExit:
770             m_state.setIsValid(false);
771             break;
772         case Array::Generic:
773             clobberWorld(node->codeOrigin, indexInBlock);
774             forNode(node).makeTop();
775             break;
776         case Array::String:
777             if (node->arrayMode().isOutOfBounds()) {
778                 // If the watchpoint was still valid we could totally set this to be
779                 // SpecString | SpecOther. Except that we'd have to be careful. If we
780                 // tested the watchpoint state here then it could change by the time
781                 // we got to the backend. So to do this right, we'd have to get the
782                 // fixup phase to check the watchpoint state and then bake into the
783                 // GetByVal operation the fact that we're using a watchpoint, using
784                 // something like Array::SaneChain (except not quite, because that
785                 // implies an in-bounds access). None of this feels like it's worth it,
786                 // so we're going with TOP for now.
787                 forNode(node).makeTop();
788             } else
789                 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
790             break;
791         case Array::Arguments:
792             forNode(node).makeTop();
793             break;
794         case Array::Int32:
795             if (node->arrayMode().isOutOfBounds()) {
796                 clobberWorld(node->codeOrigin, indexInBlock);
797                 forNode(node).makeTop();
798             } else
799                 forNode(node).setType(SpecInt32);
800             break;
801         case Array::Double:
802             if (node->arrayMode().isOutOfBounds()) {
803                 clobberWorld(node->codeOrigin, indexInBlock);
804                 forNode(node).makeTop();
805             } else if (node->arrayMode().isSaneChain())
806                 forNode(node).setType(SpecDouble);
807             else
808                 forNode(node).setType(SpecDoubleReal);
809             break;
810         case Array::Contiguous:
811         case Array::ArrayStorage:
812         case Array::SlowPutArrayStorage:
813             if (node->arrayMode().isOutOfBounds())
814                 clobberWorld(node->codeOrigin, indexInBlock);
815             forNode(node).makeTop();
816             break;
817         case Array::Int8Array:
818             forNode(node).setType(SpecInt32);
819             break;
820         case Array::Int16Array:
821             forNode(node).setType(SpecInt32);
822             break;
823         case Array::Int32Array:
824             forNode(node).setType(SpecInt32);
825             break;
826         case Array::Uint8Array:
827             forNode(node).setType(SpecInt32);
828             break;
829         case Array::Uint8ClampedArray:
830             forNode(node).setType(SpecInt32);
831             break;
832         case Array::Uint16Array:
833             forNode(node).setType(SpecInt32);
834             break;
835         case Array::Uint32Array:
836             if (node->shouldSpeculateInteger())
837                 forNode(node).setType(SpecInt32);
838             else
839                 forNode(node).setType(SpecDouble);
840             break;
841         case Array::Float32Array:
842             forNode(node).setType(SpecDouble);
843             break;
844         case Array::Float64Array:
845             forNode(node).setType(SpecDouble);
846             break;
847         default:
848             RELEASE_ASSERT_NOT_REACHED();
849             break;
850         }
851         break;
852     }
853             
854     case PutByVal:
855     case PutByValAlias: {
856         node->setCanExit(true);
857         switch (node->arrayMode().modeForPut().type()) {
858         case Array::ForceExit:
859             m_state.setIsValid(false);
860             break;
861         case Array::Generic:
862             clobberWorld(node->codeOrigin, indexInBlock);
863             break;
864         case Array::Int32:
865             if (node->arrayMode().isOutOfBounds())
866                 clobberWorld(node->codeOrigin, indexInBlock);
867             break;
868         case Array::Double:
869             if (node->arrayMode().isOutOfBounds())
870                 clobberWorld(node->codeOrigin, indexInBlock);
871             break;
872         case Array::Contiguous:
873         case Array::ArrayStorage:
874             if (node->arrayMode().isOutOfBounds())
875                 clobberWorld(node->codeOrigin, indexInBlock);
876             break;
877         case Array::SlowPutArrayStorage:
878             if (node->arrayMode().mayStoreToHole())
879                 clobberWorld(node->codeOrigin, indexInBlock);
880             break;
881         default:
882             break;
883         }
884         break;
885     }
886             
887     case ArrayPush:
888         node->setCanExit(true);
889         clobberWorld(node->codeOrigin, indexInBlock);
890         forNode(node).setType(SpecNumber);
891         break;
892             
893     case ArrayPop:
894         node->setCanExit(true);
895         clobberWorld(node->codeOrigin, indexInBlock);
896         forNode(node).makeTop();
897         break;
898             
899     case RegExpExec:
900         forNode(node).makeTop();
901         break;
902
903     case RegExpTest:
904         forNode(node).setType(SpecBoolean);
905         break;
906             
907     case Jump:
908         break;
909             
910     case Branch: {
911         Node* child = node->child1().node();
912         BooleanResult result = booleanResult(node, forNode(child));
913         if (result == DefinitelyTrue) {
914             m_state.setBranchDirection(TakeTrue);
915             break;
916         }
917         if (result == DefinitelyFalse) {
918             m_state.setBranchDirection(TakeFalse);
919             break;
920         }
921         // FIXME: The above handles the trivial cases of sparse conditional
922         // constant propagation, but we can do better:
923         // We can specialize the source variable's value on each direction of
924         // the branch.
925         node->setCanExit(true); // This is overly conservative.
926         m_state.setBranchDirection(TakeBoth);
927         break;
928     }
929         
930     case Switch: {
931         // Nothing to do for now.
932         // FIXME: Do sparse conditional things.
933         break;
934     }
935             
936     case Return:
937         m_state.setIsValid(false);
938         break;
939         
940     case Throw:
941     case ThrowReferenceError:
942         m_state.setIsValid(false);
943         node->setCanExit(true);
944         break;
945             
946     case ToPrimitive: {
947         JSValue childConst = forNode(node->child1()).value();
948         if (childConst && childConst.isNumber() && trySetConstant(node, childConst)) {
949             m_state.setFoundConstants(true);
950             break;
951         }
952         
953         ASSERT(node->child1().useKind() == UntypedUse);
954         
955         AbstractValue& source = forNode(node->child1());
956         AbstractValue& destination = forNode(node);
957         
958         // NB. The more canonical way of writing this would have been:
959         //
960         // destination = source;
961         // if (destination.m_type & !(SpecNumber | SpecString | SpecBoolean)) {
962         //     destination.filter(SpecNumber | SpecString | SpecBoolean);
963         //     AbstractValue string;
964         //     string.set(vm->stringStructure);
965         //     destination.merge(string);
966         // }
967         //
968         // The reason why this would, in most other cases, have been better is that
969         // then destination would preserve any non-SpeculatedType knowledge of source.
970         // As it stands, the code below forgets any non-SpeculatedType knowledge that
971         // source would have had. Fortunately, though, for things like strings and
972         // numbers and booleans, we don't care about the non-SpeculatedType knowedge:
973         // the structure won't tell us anything we don't already know, and neither
974         // will ArrayModes. And if the source was a meaningful constant then we
975         // would have handled that above. Unfortunately, this does mean that
976         // ToPrimitive will currently forget string constants. But that's not a big
977         // deal since we don't do any optimization on those currently.
978         
979         clobberWorld(node->codeOrigin, indexInBlock);
980         
981         SpeculatedType type = source.m_type;
982         if (type & ~(SpecNumber | SpecString | SpecBoolean)) {
983             type &= (SpecNumber | SpecString | SpecBoolean);
984             type |= SpecString;
985         }
986         destination.setType(type);
987         if (destination.isClear())
988             m_state.setIsValid(false);
989         break;
990     }
991         
992     case ToString: {
993         switch (node->child1().useKind()) {
994         case StringObjectUse:
995             // This also filters that the StringObject has the primordial StringObject
996             // structure.
997             filter(
998                 node->child1(),
999                 m_graph.globalObjectFor(node->codeOrigin)->stringObjectStructure());
1000             node->setCanExit(true); // We could be more precise but it's likely not worth it.
1001             break;
1002         case StringOrStringObjectUse:
1003             node->setCanExit(true); // We could be more precise but it's likely not worth it.
1004             break;
1005         case CellUse:
1006         case UntypedUse:
1007             clobberWorld(node->codeOrigin, indexInBlock);
1008             break;
1009         default:
1010             RELEASE_ASSERT_NOT_REACHED();
1011             break;
1012         }
1013         forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
1014         break;
1015     }
1016         
1017     case NewStringObject: {
1018         ASSERT(node->structure()->classInfo() == &StringObject::s_info);
1019         forNode(node).set(m_graph, node->structure());
1020         break;
1021     }
1022             
1023     case NewArray:
1024         node->setCanExit(true);
1025         forNode(node).set(
1026             m_graph,
1027             m_graph.globalObjectFor(node->codeOrigin)->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()));
1028         m_state.setHaveStructures(true);
1029         break;
1030         
1031     case NewArrayBuffer:
1032         node->setCanExit(true);
1033         forNode(node).set(
1034             m_graph,
1035             m_graph.globalObjectFor(node->codeOrigin)->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()));
1036         m_state.setHaveStructures(true);
1037         break;
1038
1039     case NewArrayWithSize:
1040         node->setCanExit(true);
1041         forNode(node).setType(SpecArray);
1042         m_state.setHaveStructures(true);
1043         break;
1044             
1045     case NewRegexp:
1046         forNode(node).set(m_graph, m_graph.globalObjectFor(node->codeOrigin)->regExpStructure());
1047         m_state.setHaveStructures(true);
1048         break;
1049             
1050     case ToThis: {
1051         AbstractValue& source = forNode(node->child1());
1052         AbstractValue& destination = forNode(node);
1053             
1054         destination = source;
1055         destination.merge(SpecObjectOther);
1056         break;
1057     }
1058
1059     case CreateThis: {
1060         forNode(node).setType(SpecFinalObject);
1061         break;
1062     }
1063         
1064     case AllocationProfileWatchpoint:
1065         node->setCanExit(true);
1066         break;
1067
1068     case NewObject:
1069         forNode(node).set(m_graph, node->structure());
1070         m_state.setHaveStructures(true);
1071         break;
1072         
1073     case CreateActivation:
1074         forNode(node).set(
1075             m_graph, m_codeBlock->globalObjectFor(node->codeOrigin)->activationStructure());
1076         m_state.setHaveStructures(true);
1077         break;
1078         
1079     case CreateArguments:
1080         forNode(node).set(
1081             m_graph, m_codeBlock->globalObjectFor(node->codeOrigin)->argumentsStructure());
1082         m_state.setHaveStructures(true);
1083         break;
1084         
1085     case TearOffActivation:
1086     case TearOffArguments:
1087         // Does nothing that is user-visible.
1088         break;
1089
1090     case CheckArgumentsNotCreated:
1091         if (isEmptySpeculation(
1092                 m_state.variables().operand(
1093                     m_graph.argumentsRegisterFor(node->codeOrigin)).m_type))
1094             m_state.setFoundConstants(true);
1095         else
1096             node->setCanExit(true);
1097         break;
1098         
1099     case GetMyArgumentsLength:
1100         // We know that this executable does not escape its arguments, so we can optimize
1101         // the arguments a bit. Note that this is not sufficient to force constant folding
1102         // of GetMyArgumentsLength, because GetMyArgumentsLength is a clobbering operation.
1103         // We perform further optimizations on this later on.
1104         if (node->codeOrigin.inlineCallFrame) {
1105             forNode(node).set(
1106                 m_graph, jsNumber(node->codeOrigin.inlineCallFrame->arguments.size() - 1));
1107         } else
1108             forNode(node).setType(SpecInt32);
1109         node->setCanExit(
1110             !isEmptySpeculation(
1111                 m_state.variables().operand(
1112                     m_graph.argumentsRegisterFor(node->codeOrigin)).m_type));
1113         break;
1114         
1115     case GetMyArgumentsLengthSafe:
1116         // This potentially clobbers all structures if the arguments object had a getter
1117         // installed on the length property.
1118         clobberWorld(node->codeOrigin, indexInBlock);
1119         // We currently make no guarantee about what this returns because it does not
1120         // speculate that the length property is actually a length.
1121         forNode(node).makeTop();
1122         break;
1123         
1124     case GetMyArgumentByVal:
1125         node->setCanExit(true);
1126         // We know that this executable does not escape its arguments, so we can optimize
1127         // the arguments a bit. Note that this ends up being further optimized by the
1128         // ArgumentsSimplificationPhase.
1129         forNode(node).makeTop();
1130         break;
1131         
1132     case GetMyArgumentByValSafe:
1133         node->setCanExit(true);
1134         // This potentially clobbers all structures if the property we're accessing has
1135         // a getter. We don't speculate against this.
1136         clobberWorld(node->codeOrigin, indexInBlock);
1137         // And the result is unknown.
1138         forNode(node).makeTop();
1139         break;
1140         
1141     case NewFunction: {
1142         AbstractValue& value = forNode(node);
1143         value = forNode(node->child1());
1144         
1145         if (!(value.m_type & SpecEmpty)) {
1146             m_state.setFoundConstants(true);
1147             break;
1148         }
1149
1150         value.setType((value.m_type & ~SpecEmpty) | SpecFunction);
1151         break;
1152     }
1153
1154     case NewFunctionExpression:
1155     case NewFunctionNoCheck:
1156         forNode(node).set(
1157             m_graph, m_codeBlock->globalObjectFor(node->codeOrigin)->functionStructure());
1158         break;
1159         
1160     case GetCallee:
1161         forNode(node).setType(SpecFunction);
1162         break;
1163         
1164     case SetCallee:
1165     case SetMyScope:
1166         break;
1167             
1168     case GetScope: // FIXME: We could get rid of these if we know that the JSFunction is a constant. https://bugs.webkit.org/show_bug.cgi?id=106202
1169     case GetMyScope:
1170     case SkipTopScope:
1171         forNode(node).setType(SpecCellOther);
1172         break;
1173
1174     case SkipScope: {
1175         JSValue child = forNode(node->child1()).value();
1176         if (child && trySetConstant(node, JSValue(jsCast<JSScope*>(child.asCell())->next()))) {
1177             m_state.setFoundConstants(true);
1178             break;
1179         }
1180         forNode(node).setType(SpecCellOther);
1181         break;
1182     }
1183
1184     case GetClosureRegisters:
1185         forNode(node).clear(); // The result is not a JS value.
1186         break;
1187
1188     case GetClosureVar:
1189         forNode(node).makeTop();
1190         break;
1191             
1192     case PutClosureVar:
1193         clobberCapturedVars(node->codeOrigin);
1194         break;
1195             
1196     case GetById:
1197     case GetByIdFlush:
1198         node->setCanExit(true);
1199         if (!node->prediction()) {
1200             m_state.setIsValid(false);
1201             break;
1202         }
1203         if (isCellSpeculation(node->child1()->prediction())) {
1204             if (Structure* structure = forNode(node->child1()).bestProvenStructure()) {
1205                 GetByIdStatus status = GetByIdStatus::computeFor(
1206                     m_graph.m_vm, structure,
1207                     m_graph.identifiers()[node->identifierNumber()]);
1208                 if (status.isSimple()) {
1209                     // Assert things that we can't handle and that the computeFor() method
1210                     // above won't be able to return.
1211                     ASSERT(status.structureSet().size() == 1);
1212                     ASSERT(!status.chain());
1213                     
1214                     if (status.specificValue())
1215                         forNode(node).set(m_graph, status.specificValue());
1216                     else
1217                         forNode(node).makeTop();
1218                     filter(node->child1(), status.structureSet());
1219                     
1220                     m_state.setFoundConstants(true);
1221                     break;
1222                 }
1223             }
1224         }
1225         clobberWorld(node->codeOrigin, indexInBlock);
1226         forNode(node).makeTop();
1227         break;
1228             
1229     case GetArrayLength:
1230         node->setCanExit(true); // Lies, but it's true for the common case of JSArray, so it's good enough.
1231         forNode(node).setType(SpecInt32);
1232         break;
1233         
1234     case CheckExecutable: {
1235         // FIXME: We could track executables in AbstractValue, which would allow us to get rid of these checks
1236         // more thoroughly. https://bugs.webkit.org/show_bug.cgi?id=106200
1237         // FIXME: We could eliminate these entirely if we know the exact value that flows into this.
1238         // https://bugs.webkit.org/show_bug.cgi?id=106201
1239         node->setCanExit(true);
1240         break;
1241     }
1242
1243     case CheckStructure:
1244     case ForwardCheckStructure: {
1245         // FIXME: We should be able to propagate the structure sets of constants (i.e. prototypes).
1246         AbstractValue& value = forNode(node->child1());
1247         ASSERT(!(value.m_type & ~SpecCell)); // Edge filtering should have already ensured this.
1248
1249         StructureSet& set = node->structureSet();
1250
1251         if (value.m_currentKnownStructure.isSubsetOf(set)) {
1252             m_state.setFoundConstants(true);
1253             break;
1254         }
1255
1256         node->setCanExit(true);
1257
1258         // If this structure check is attempting to prove knowledge already held in
1259         // the futurePossibleStructure set then the constant folding phase should
1260         // turn this into a watchpoint instead.
1261         if (value.m_futurePossibleStructure.isSubsetOf(set)
1262             && value.m_futurePossibleStructure.hasSingleton()) {
1263             m_state.setFoundConstants(true);
1264             filter(value, value.m_futurePossibleStructure.singleton());
1265             break;
1266         }
1267
1268         filter(value, set);
1269         m_state.setHaveStructures(true);
1270         break;
1271     }
1272         
1273     case StructureTransitionWatchpoint:
1274     case ForwardStructureTransitionWatchpoint: {
1275         AbstractValue& value = forNode(node->child1());
1276
1277         // It's only valid to issue a structure transition watchpoint if we already
1278         // know that the watchpoint covers a superset of the structures known to
1279         // belong to the set of future structures that this value may have.
1280         // Currently, we only issue singleton watchpoints (that check one structure)
1281         // and our futurePossibleStructure set can only contain zero, one, or an
1282         // infinity of structures.
1283         ASSERT(
1284             value.m_futurePossibleStructure.isSubsetOf(StructureSet(node->structure()))
1285             || m_graph.watchpoints().shouldAssumeMixedState(node->structure()->transitionWatchpointSet()));
1286         
1287         filter(value, node->structure());
1288         m_state.setHaveStructures(true);
1289         node->setCanExit(true);
1290         break;
1291     }
1292             
1293     case PutStructure:
1294     case PhantomPutStructure:
1295         if (!forNode(node->child1()).m_currentKnownStructure.isClear()) {
1296             clobberStructures(indexInBlock);
1297             forNode(node->child1()).set(m_graph, node->structureTransitionData().newStructure);
1298             m_state.setHaveStructures(true);
1299         }
1300         break;
1301     case GetButterfly:
1302     case AllocatePropertyStorage:
1303     case ReallocatePropertyStorage:
1304         forNode(node).clear(); // The result is not a JS value.
1305         break;
1306     case ForwardCheckArray:
1307     case CheckArray: {
1308         if (node->arrayMode().alreadyChecked(m_graph, node, forNode(node->child1()))) {
1309             m_state.setFoundConstants(true);
1310             break;
1311         }
1312         node->setCanExit(true); // Lies, but this is followed by operations (like GetByVal) that always exit, so there is no point in us trying to be clever here.
1313         switch (node->arrayMode().type()) {
1314         case Array::String:
1315             filter(node->child1(), SpecString);
1316             break;
1317         case Array::Int32:
1318         case Array::Double:
1319         case Array::Contiguous:
1320         case Array::ArrayStorage:
1321         case Array::SlowPutArrayStorage:
1322             break;
1323         case Array::Arguments:
1324             filter(node->child1(), SpecArguments);
1325             break;
1326         case Array::Int8Array:
1327             filter(node->child1(), SpecInt8Array);
1328             break;
1329         case Array::Int16Array:
1330             filter(node->child1(), SpecInt16Array);
1331             break;
1332         case Array::Int32Array:
1333             filter(node->child1(), SpecInt32Array);
1334             break;
1335         case Array::Uint8Array:
1336             filter(node->child1(), SpecUint8Array);
1337             break;
1338         case Array::Uint8ClampedArray:
1339             filter(node->child1(), SpecUint8ClampedArray);
1340             break;
1341         case Array::Uint16Array:
1342             filter(node->child1(), SpecUint16Array);
1343             break;
1344         case Array::Uint32Array:
1345             filter(node->child1(), SpecUint32Array);
1346             break;
1347         case Array::Float32Array:
1348             filter(node->child1(), SpecFloat32Array);
1349             break;
1350         case Array::Float64Array:
1351             filter(node->child1(), SpecFloat64Array);
1352             break;
1353         default:
1354             RELEASE_ASSERT_NOT_REACHED();
1355             break;
1356         }
1357         filterArrayModes(node->child1(), node->arrayMode().arrayModesThatPassFiltering());
1358         m_state.setHaveStructures(true);
1359         break;
1360     }
1361     case Arrayify: {
1362         if (node->arrayMode().alreadyChecked(m_graph, node, forNode(node->child1()))) {
1363             m_state.setFoundConstants(true);
1364             break;
1365         }
1366         ASSERT(node->arrayMode().conversion() == Array::Convert
1367             || node->arrayMode().conversion() == Array::RageConvert);
1368         node->setCanExit(true);
1369         clobberStructures(indexInBlock);
1370         filterArrayModes(node->child1(), node->arrayMode().arrayModesThatPassFiltering());
1371         m_state.setHaveStructures(true);
1372         break;
1373     }
1374     case ArrayifyToStructure: {
1375         AbstractValue& value = forNode(node->child1());
1376         StructureSet set = node->structure();
1377         if (value.m_futurePossibleStructure.isSubsetOf(set)
1378             || value.m_currentKnownStructure.isSubsetOf(set))
1379             m_state.setFoundConstants(true);
1380         node->setCanExit(true);
1381         clobberStructures(indexInBlock);
1382         filter(value, set);
1383         m_state.setHaveStructures(true);
1384         break;
1385     }
1386     case GetIndexedPropertyStorage: {
1387         forNode(node).clear();
1388         break; 
1389     }
1390     case GetByOffset: {
1391         forNode(node).makeTop();
1392         break;
1393     }
1394             
1395     case PutByOffset: {
1396         break;
1397     }
1398             
1399     case CheckFunction: {
1400         JSValue value = forNode(node->child1()).value();
1401         if (value == node->function()) {
1402             m_state.setFoundConstants(true);
1403             ASSERT(value);
1404             break;
1405         }
1406         
1407         node->setCanExit(true); // Lies! We can do better.
1408         filterByValue(node->child1(), node->function());
1409         break;
1410     }
1411         
1412     case PutById:
1413     case PutByIdDirect:
1414         node->setCanExit(true);
1415         if (Structure* structure = forNode(node->child1()).bestProvenStructure()) {
1416             PutByIdStatus status = PutByIdStatus::computeFor(
1417                 m_graph.m_vm,
1418                 m_graph.globalObjectFor(node->codeOrigin),
1419                 structure,
1420                 m_graph.identifiers()[node->identifierNumber()],
1421                 node->op() == PutByIdDirect);
1422             if (status.isSimpleReplace()) {
1423                 filter(node->child1(), structure);
1424                 m_state.setFoundConstants(true);
1425                 break;
1426             }
1427             if (status.isSimpleTransition()) {
1428                 clobberStructures(indexInBlock);
1429                 forNode(node->child1()).set(m_graph, status.newStructure());
1430                 m_state.setHaveStructures(true);
1431                 m_state.setFoundConstants(true);
1432                 break;
1433             }
1434         }
1435         clobberWorld(node->codeOrigin, indexInBlock);
1436         break;
1437         
1438     case In:
1439         // FIXME: We can determine when the property definitely exists based on abstract
1440         // value information.
1441         clobberWorld(node->codeOrigin, indexInBlock);
1442         forNode(node).setType(SpecBoolean);
1443         break;
1444             
1445     case GetGlobalVar:
1446         forNode(node).makeTop();
1447         break;
1448         
1449     case GlobalVarWatchpoint:
1450     case VarInjectionWatchpoint:
1451         node->setCanExit(true);
1452         break;
1453             
1454     case PutGlobalVar:
1455         break;
1456             
1457     case CheckHasInstance:
1458         node->setCanExit(true);
1459         // Sadly, we don't propagate the fact that we've done CheckHasInstance
1460         break;
1461             
1462     case InstanceOf:
1463         node->setCanExit(true);
1464         // Again, sadly, we don't propagate the fact that we've done InstanceOf
1465         forNode(node).setType(SpecBoolean);
1466         break;
1467             
1468     case Phi:
1469         RELEASE_ASSERT(m_graph.m_form == SSA);
1470         // The state of this node would have already been decided.
1471         break;
1472         
1473     case Upsilon: {
1474         AbstractValue& value = forNode(node->child1());
1475         forNode(node) = value;
1476         forNode(node->phi()) = value;
1477         break;
1478     }
1479         
1480     case Flush:
1481     case PhantomLocal:
1482     case Breakpoint:
1483         break;
1484             
1485     case Call:
1486     case Construct:
1487         node->setCanExit(true);
1488         clobberWorld(node->codeOrigin, indexInBlock);
1489         forNode(node).makeTop();
1490         break;
1491
1492     case ForceOSRExit:
1493     case ForwardForceOSRExit:
1494         node->setCanExit(true);
1495         m_state.setIsValid(false);
1496         break;
1497             
1498     case CheckWatchdogTimer:
1499         node->setCanExit(true);
1500         break;
1501             
1502     case Phantom:
1503     case InlineStart:
1504     case CountExecution:
1505         break;
1506         
1507     case LastNodeType:
1508         RELEASE_ASSERT_NOT_REACHED();
1509         break;
1510     }
1511     
1512     return m_state.isValid();
1513 }
1514
1515 template<typename AbstractStateType>
1516 bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned indexInBlock)
1517 {
1518     return executeEffects(indexInBlock, m_state.block()->at(indexInBlock));
1519 }
1520
1521 template<typename AbstractStateType>
1522 bool AbstractInterpreter<AbstractStateType>::execute(unsigned indexInBlock)
1523 {
1524     Node* node = m_state.block()->at(indexInBlock);
1525     if (!startExecuting(node))
1526         return true;
1527     
1528     executeEdges(node);
1529     return executeEffects(indexInBlock, node);
1530 }
1531
1532 template<typename AbstractStateType>
1533 void AbstractInterpreter<AbstractStateType>::clobberWorld(
1534     const CodeOrigin& codeOrigin, unsigned indexInBlock)
1535 {
1536     clobberCapturedVars(codeOrigin);
1537     clobberStructures(indexInBlock);
1538 }
1539
1540 template<typename AbstractStateType>
1541 void AbstractInterpreter<AbstractStateType>::clobberCapturedVars(const CodeOrigin& codeOrigin)
1542 {
1543     if (codeOrigin.inlineCallFrame) {
1544         const BitVector& capturedVars = codeOrigin.inlineCallFrame->capturedVars;
1545         for (size_t i = capturedVars.size(); i--;) {
1546             if (!capturedVars.quickGet(i))
1547                 continue;
1548             m_state.variables().local(i).makeTop();
1549         }
1550     } else {
1551         for (size_t i = m_codeBlock->m_numVars; i--;) {
1552             if (m_codeBlock->isCaptured(i))
1553                 m_state.variables().local(i).makeTop();
1554         }
1555     }
1556
1557     for (size_t i = m_state.variables().numberOfArguments(); i--;) {
1558         if (m_codeBlock->isCaptured(argumentToOperand(i)))
1559             m_state.variables().argument(i).makeTop();
1560     }
1561 }
1562
1563 template<typename AbstractStateType>
1564 void AbstractInterpreter<AbstractStateType>::clobberStructures(unsigned indexInBlock)
1565 {
1566     if (!m_state.haveStructures())
1567         return;
1568     for (size_t i = indexInBlock + 1; i--;)
1569         forNode(m_state.block()->at(i)).clobberStructures();
1570     if (m_graph.m_form == SSA) {
1571         HashSet<Node*>::iterator iter = m_state.block()->ssa->liveAtHead.begin();
1572         HashSet<Node*>::iterator end = m_state.block()->ssa->liveAtHead.end();
1573         for (; iter != end; ++iter)
1574             forNode(*iter).clobberStructures();
1575     }
1576     for (size_t i = m_state.variables().numberOfArguments(); i--;)
1577         m_state.variables().argument(i).clobberStructures();
1578     for (size_t i = m_state.variables().numberOfLocals(); i--;)
1579         m_state.variables().local(i).clobberStructures();
1580     m_state.setHaveStructures(true);
1581     m_state.setDidClobber(true);
1582 }
1583
1584 template<typename AbstractStateType>
1585 void AbstractInterpreter<AbstractStateType>::dump(PrintStream& out)
1586 {
1587     CommaPrinter comma(" ");
1588     if (m_graph.m_form == SSA) {
1589         HashSet<Node*>::iterator iter = m_state.block()->ssa->liveAtHead.begin();
1590         HashSet<Node*>::iterator end = m_state.block()->ssa->liveAtHead.end();
1591         for (; iter != end; ++iter) {
1592             Node* node = *iter;
1593             AbstractValue& value = forNode(node);
1594             if (value.isClear())
1595                 continue;
1596             out.print(comma, node, ":", value);
1597         }
1598     }
1599     for (size_t i = 0; i < m_state.block()->size(); ++i) {
1600         Node* node = m_state.block()->at(i);
1601         AbstractValue& value = forNode(node);
1602         if (value.isClear())
1603             continue;
1604         out.print(comma, node, ":", value);
1605     }
1606 }
1607
1608 template<typename AbstractStateType>
1609 FiltrationResult AbstractInterpreter<AbstractStateType>::filter(
1610     AbstractValue& value, const StructureSet& set)
1611 {
1612     if (value.filter(m_graph, set) == FiltrationOK)
1613         return FiltrationOK;
1614     m_state.setIsValid(false);
1615     return Contradiction;
1616 }
1617
1618 template<typename AbstractStateType>
1619 FiltrationResult AbstractInterpreter<AbstractStateType>::filterArrayModes(
1620     AbstractValue& value, ArrayModes arrayModes)
1621 {
1622     if (value.filterArrayModes(arrayModes) == FiltrationOK)
1623         return FiltrationOK;
1624     m_state.setIsValid(false);
1625     return Contradiction;
1626 }
1627
1628 template<typename AbstractStateType>
1629 FiltrationResult AbstractInterpreter<AbstractStateType>::filter(
1630     AbstractValue& value, SpeculatedType type)
1631 {
1632     if (value.filter(type) == FiltrationOK)
1633         return FiltrationOK;
1634     m_state.setIsValid(false);
1635     return Contradiction;
1636 }
1637
1638 template<typename AbstractStateType>
1639 FiltrationResult AbstractInterpreter<AbstractStateType>::filterByValue(
1640     AbstractValue& abstractValue, JSValue concreteValue)
1641 {
1642     if (abstractValue.filterByValue(concreteValue) == FiltrationOK)
1643         return FiltrationOK;
1644     m_state.setIsValid(false);
1645     return Contradiction;
1646 }
1647
1648 } } // namespace JSC::DFG
1649
1650 #endif // ENABLE(DFG_JIT)
1651
1652 #endif // DFGAbstractInterpreterInlines_h
1653