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