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