/*
 * Copyright (C) 2013-2019 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */

#include "config.h"
#include "DFGStrengthReductionPhase.h"

#if ENABLE(DFG_JIT)

#include "DFGAbstractHeap.h"
#include "DFGClobberize.h"
#include "DFGGraph.h"
#include "DFGInsertionSet.h"
#include "DFGPhase.h"
#include "DFGPredictionPropagationPhase.h"
#include "DFGVariableAccessDataDump.h"
#include "JSCInlines.h"
#include "MathCommon.h"
#include "RegExpObject.h"
#include "StringPrototype.h"
#include <cstdlib>
#include <wtf/text/StringBuilder.h>

namespace JSC { namespace DFG {

class StrengthReductionPhase : public Phase {
    static constexpr bool verbose = false;
    
public:
    StrengthReductionPhase(Graph& graph)
        : Phase(graph, "strength reduction")
        , m_insertionSet(graph)
    {
    }
    
    bool run()
    {
        ASSERT(m_graph.m_fixpointState == FixpointNotConverged);
        
        m_changed = false;
        
        for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
            m_block = m_graph.block(blockIndex);
            if (!m_block)
                continue;
            for (m_nodeIndex = 0; m_nodeIndex < m_block->size(); ++m_nodeIndex) {
                m_node = m_block->at(m_nodeIndex);
                handleNode();
            }
            m_insertionSet.execute(m_block);
        }
        
        return m_changed;
    }

private:
    void handleNode()
    {
        switch (m_node->op()) {
        case ArithBitOr:
            handleCommutativity();

            if (m_node->child1().useKind() != UntypedUse && m_node->child2()->isInt32Constant() && !m_node->child2()->asInt32()) {
                convertToIdentityOverChild1();
                break;
            }
            break;
            
        case ArithBitXor:
        case ArithBitAnd:
            handleCommutativity();
            break;
            
        case ArithBitLShift:
        case ArithBitRShift:
        case BitURShift:
            if (m_node->child1().useKind() != UntypedUse && m_node->child2()->isInt32Constant() && !(m_node->child2()->asInt32() & 0x1f)) {
                convertToIdentityOverChild1();
                break;
            }
            break;
            
        case UInt32ToNumber:
            if (m_node->child1()->op() == BitURShift
                && m_node->child1()->child2()->isInt32Constant()
                && (m_node->child1()->child2()->asInt32() & 0x1f)
                && m_node->arithMode() != Arith::DoOverflow) {
                m_node->convertToIdentity();
                m_changed = true;
                break;
            }
            break;
            
        case ArithAdd:
            handleCommutativity();
            
            if (m_node->child2()->isInt32Constant() && !m_node->child2()->asInt32()) {
                convertToIdentityOverChild1();
                break;
            }
            break;
            
        case ValueMul:
        case ValueBitOr:
        case ValueBitAnd:
        case ValueBitXor: {
            if (m_node->binaryUseKind() == BigIntUse)
                handleCommutativity();
            break;
        }

        case ArithMul: {
            handleCommutativity();
            Edge& child2 = m_node->child2();
            if (child2->isNumberConstant() && child2->asNumber() == 2) {
                switch (m_node->binaryUseKind()) {
                case DoubleRepUse:
                    // It is always valuable to get rid of a double multiplication by 2.
                    // We won't have half-register dependencies issues on x86 and we won't have to load the constants.
                    m_node->setOp(ArithAdd);
                    child2.setNode(m_node->child1().node());
                    m_changed = true;
                    break;
#if USE(JSVALUE64)
                case Int52RepUse:
#endif
                case Int32Use:
                    // For integers, we can only convert compatible modes.
                    // ArithAdd does handle do negative zero check for example.
                    if (m_node->arithMode() == Arith::CheckOverflow || m_node->arithMode() == Arith::Unchecked) {
                        m_node->setOp(ArithAdd);
                        child2.setNode(m_node->child1().node());
                        m_changed = true;
                    }
                    break;
                default:
                    break;
                }
            }
            break;
        }
        case ArithSub:
            if (m_node->child2()->isInt32Constant()
                && m_node->isBinaryUseKind(Int32Use)) {
                int32_t value = m_node->child2()->asInt32();
                if (value != INT32_MIN) {
                    m_node->setOp(ArithAdd);
                    m_node->child2().setNode(
                        m_insertionSet.insertConstant(
                            m_nodeIndex, m_node->origin, jsNumber(-value)));
                    m_changed = true;
                    break;
                }
            }
            break;

        case ArithPow:
            if (m_node->child2()->isNumberConstant()) {
                double yOperandValue = m_node->child2()->asNumber();
                if (yOperandValue == 1) {
                    convertToIdentityOverChild1();
                    m_changed = true;
                } else if (yOperandValue == 2) {
                    m_node->setOp(ArithMul);
                    m_node->child2() = m_node->child1();
                    m_changed = true;
                }
            }
            break;

        case ArithMod:
            // On Integers
            // In: ArithMod(ArithMod(x, const1), const2)
            // Out: Identity(ArithMod(x, const1))
            //     if const1 <= const2.
            if (m_node->binaryUseKind() == Int32Use
                && m_node->child2()->isInt32Constant()
                && m_node->child1()->op() == ArithMod
                && m_node->child1()->binaryUseKind() == Int32Use
                && m_node->child1()->child2()->isInt32Constant()
                && std::abs(m_node->child1()->child2()->asInt32()) <= std::abs(m_node->child2()->asInt32())) {
                    convertToIdentityOverChild1();
            }
            break;

        case ArithDiv:
            // Transform
            //    ArithDiv(x, constant)
            // Into
            //    ArithMul(x, 1 / constant)
            // if the operation has the same result.
            if (m_node->isBinaryUseKind(DoubleRepUse)
                && m_node->child2()->isNumberConstant()) {

                if (Optional<double> reciprocal = safeReciprocalForDivByConst(m_node->child2()->asNumber())) {
                    Node* reciprocalNode = m_insertionSet.insertConstant(m_nodeIndex, m_node->origin, jsDoubleNumber(*reciprocal), DoubleConstant);
                    m_node->setOp(ArithMul);
                    m_node->child2() = Edge(reciprocalNode, DoubleRepUse);
                    m_changed = true;
                    break;
                }
            }
            break;

        case ValueRep:
        case Int52Rep: {
            // This short-circuits circuitous conversions, like ValueRep(Int52Rep(value)).
            
            // The only speculation that we would do beyond validating that we have a type that
            // can be represented a certain way is an Int32 check that would appear on Int52Rep
            // nodes. For now, if we see this and the final type we want is an Int52, we use it
            // as an excuse not to fold. The only thing we would need is a Int52RepInt32Use kind.
            bool hadInt32Check = false;
            if (m_node->op() == Int52Rep) {
                if (m_node->child1().useKind() != Int32Use)
                    break;
                hadInt32Check = true;
            }
            for (Node* node = m_node->child1().node(); ; node = node->child1().node()) {
                if (canonicalResultRepresentation(node->result()) ==
                    canonicalResultRepresentation(m_node->result())) {
                    m_insertionSet.insertCheck(m_graph, m_nodeIndex, m_node);
                    if (hadInt32Check) {
                        // FIXME: Consider adding Int52RepInt32Use or even DoubleRepInt32Use,
                        // which would be super weird. The latter would only arise in some
                        // seriously circuitous conversions.
                        if (canonicalResultRepresentation(node->result()) != NodeResultJS)
                            break;
                        
                        m_insertionSet.insertCheck(
                            m_nodeIndex, m_node->origin, Edge(node, Int32Use));
                    }
                    m_node->child1() = node->defaultEdge();
                    m_node->convertToIdentity();
                    m_changed = true;
                    break;
                }
                
                switch (node->op()) {
                case Int52Rep:
                    if (node->child1().useKind() != Int32Use)
                        break;
                    hadInt32Check = true;
                    continue;
                    
                case ValueRep:
                    continue;
                    
                default:
                    break;
                }
                break;
            }
            break;
        }
            
        case Flush: {
            ASSERT(m_graph.m_form != SSA);

            if (m_graph.willCatchExceptionInMachineFrame(m_node->origin.semantic)) {
                // FIXME: We should be able to relax this:
                // https://bugs.webkit.org/show_bug.cgi?id=150824
                break;
            }
            
            Node* setLocal = nullptr;
            Operand operand = m_node->operand();
            
            for (unsigned i = m_nodeIndex; i--;) {
                Node* node = m_block->at(i);

                if (node->op() == SetLocal && node->operand() == operand) {
                    setLocal = node;
                    break;
                }

                if (accessesOverlap(m_graph, node, AbstractHeap(Stack, operand)))
                    break;

            }
            
            if (!setLocal)
                break;
            
            // The Flush should become a PhantomLocal at this point. This means that we want the
            // local's value during OSR, but we don't care if the value is stored to the stack. CPS
            // rethreading can canonicalize PhantomLocals for us.
            m_node->convertFlushToPhantomLocal();
            m_graph.dethread();
            m_changed = true;
            break;
        }

        // FIXME: we should probably do this in constant folding but this currently relies on OSR exit history:
        // https://bugs.webkit.org/show_bug.cgi?id=154832
        case OverridesHasInstance: {
            if (!m_node->child2().node()->isCellConstant())
                break;

            if (m_node->child2().node()->asCell() != m_graph.globalObjectFor(m_node->origin.semantic)->functionProtoHasInstanceSymbolFunction()) {
                m_graph.convertToConstant(m_node, jsBoolean(true));
                m_changed = true;

            } else if (!m_graph.hasExitSite(m_node->origin.semantic, BadTypeInfoFlags)) {
                // We optimistically assume that we will not see a function that has a custom instanceof operation as they should be rare.
                m_insertionSet.insertNode(m_nodeIndex, SpecNone, CheckTypeInfoFlags, m_node->origin, OpInfo(ImplementsDefaultHasInstance), Edge(m_node->child1().node(), CellUse));
                m_graph.convertToConstant(m_node, jsBoolean(false));
                m_changed = true;
            }

            break;
        }

        // FIXME: We have a lot of string constant-folding rules here. It would be great to
        // move these to the abstract interpreter once AbstractValue can support LazyJSValue.
        // https://bugs.webkit.org/show_bug.cgi?id=155204

        case ValueAdd: {
            if (m_node->child1()->isConstant()
                && m_node->child2()->isConstant()
                && (!!m_node->child1()->tryGetString(m_graph) || !!m_node->child2()->tryGetString(m_graph))) {
                auto tryGetConstantString = [&] (Node* node) -> String {
                    String string = node->tryGetString(m_graph);
                    if (!string.isEmpty())
                        return string;
                    JSValue value = node->constant()->value();
                    if (!value)
                        return String();
                    if (value.isInt32())
                        return String::number(value.asInt32());
                    if (value.isNumber())
                        return String::number(value.asNumber());
                    if (value.isBoolean())
                        return value.asBoolean() ? "true"_s : "false"_s;
                    if (value.isNull())
                        return "null"_s;
                    if (value.isUndefined())
                        return "undefined"_s;
                    return String();
                };

                String leftString = tryGetConstantString(m_node->child1().node());
                if (!leftString)
                    break;
                String rightString = tryGetConstantString(m_node->child2().node());
                if (!rightString)
                    break;

                StringBuilder builder;
                builder.append(leftString);
                builder.append(rightString);
                convertToLazyJSValue(m_node, LazyJSValue::newString(m_graph, builder.toString()));
                m_changed = true;
                break;
            }

            if (m_node->binaryUseKind() == BigIntUse)
                handleCommutativity();

            break;
        }

        case MakeRope:
        case StrCat: {
            String leftString = m_node->child1()->tryGetString(m_graph);
            if (!leftString)
                break;
            String rightString = m_node->child2()->tryGetString(m_graph);
            if (!rightString)
                break;
            String extraString;
            if (m_node->child3()) {
                extraString = m_node->child3()->tryGetString(m_graph);
                if (!extraString)
                    break;
            }

            StringBuilder builder;
            builder.append(leftString);
            builder.append(rightString);
            if (!!extraString)
                builder.append(extraString);

            convertToLazyJSValue(m_node, LazyJSValue::newString(m_graph, builder.toString()));
            m_changed = true;
            break;
        }

        case ToString:
        case CallStringConstructor: {
            Edge& child1 = m_node->child1();
            switch (child1.useKind()) {
            case Int32Use:
            case Int52RepUse:
            case DoubleRepUse: {
                if (child1->hasConstant()) {
                    JSValue value = child1->constant()->value();
                    if (value) {
                        String result;
                        if (value.isInt32())
                            result = String::number(value.asInt32());
                        else if (value.isNumber())
                            result = String::number(value.asNumber());

                        if (!result.isNull()) {
                            convertToLazyJSValue(m_node, LazyJSValue::newString(m_graph, result));
                            m_changed = true;
                        }
                    }
                }
                break;
            }

            default:
                break;
            }
            break;
        }

        case NumberToStringWithValidRadixConstant: {
            Edge& child1 = m_node->child1();
            if (child1->hasConstant()) {
                JSValue value = child1->constant()->value();
                if (value && value.isNumber()) {
                    String result = toStringWithRadix(value.asNumber(), m_node->validRadixConstant());
                    convertToLazyJSValue(m_node, LazyJSValue::newString(m_graph, result));
                    m_changed = true;
                }
            }
            break;
        }

        case GetArrayLength: {
            if (m_node->arrayMode().type() == Array::Generic
                || m_node->arrayMode().type() == Array::String) {
                String string = m_node->child1()->tryGetString(m_graph);
                if (!!string) {
                    m_graph.convertToConstant(m_node, jsNumber(string.length()));
                    m_changed = true;
                    break;
                }
            }
            break;
        }

        case GetGlobalObject: {
            if (JSObject* object = m_node->child1()->dynamicCastConstant<JSObject*>(vm())) {
                m_graph.convertToConstant(m_node, object->globalObject(vm()));
                m_changed = true;
                break;
            }
            break;
        }

        case RegExpExec:
        case RegExpTest:
        case RegExpMatchFast:
        case RegExpExecNonGlobalOrSticky: {
            JSGlobalObject* globalObject = m_node->child1()->dynamicCastConstant<JSGlobalObject*>(vm());
            if (!globalObject) {
                if (verbose)
                    dataLog("Giving up because no global object.\n");
                break;
            }

            if (globalObject->isHavingABadTime()) {
                if (verbose)
                    dataLog("Giving up because bad time.\n");
                break;
            }

            Node* regExpObjectNode = nullptr;
            RegExp* regExp = nullptr;
            if (m_node->op() == RegExpExec || m_node->op() == RegExpTest || m_node->op() == RegExpMatchFast) {
                regExpObjectNode = m_node->child2().node();
                if (RegExpObject* regExpObject = regExpObjectNode->dynamicCastConstant<RegExpObject*>(vm()))
                    regExp = regExpObject->regExp();
                else if (regExpObjectNode->op() == NewRegexp)
                    regExp = regExpObjectNode->castOperand<RegExp*>();
                else {
                    if (verbose)
                        dataLog("Giving up because the regexp is unknown.\n");
                    break;
                }
            } else
                regExp = m_node->castOperand<RegExp*>();

            if (m_node->op() == RegExpMatchFast) {
                if (regExp->global()) {
                    if (regExp->sticky())
                        break;
                    if (m_node->child3().useKind() != StringUse)
                        break;
                    NodeOrigin origin = m_node->origin;
                    m_insertionSet.insertNode(
                        m_nodeIndex, SpecNone, Check, origin, m_node->children.justChecks());
                    m_insertionSet.insertNode(
                        m_nodeIndex, SpecNone, SetRegExpObjectLastIndex, origin,
                        OpInfo(false),
                        Edge(regExpObjectNode, RegExpObjectUse),
                        m_insertionSet.insertConstantForUse(
                            m_nodeIndex, origin, jsNumber(0), UntypedUse));
                    origin = origin.withInvalidExit();
                    m_node->convertToRegExpMatchFastGlobalWithoutChecks(m_graph.freeze(regExp));
                    m_node->origin = origin;
                    m_changed = true;
                    break;
                }

                m_node->setOp(RegExpExec);
                m_changed = true;
                // Continue performing strength reduction onto RegExpExec node.
            }

            ASSERT(m_node->op() != RegExpMatchFast);

            unsigned lastIndex = UINT_MAX;
            if (m_node->op() != RegExpExecNonGlobalOrSticky) {
                // This will only work if we can prove what the value of lastIndex is. To do this
                // safely, we need to execute the insertion set so that we see any previous strength
                // reductions. This is needed for soundness since otherwise the effectfulness of any
                // previous strength reductions would be invisible to us.
                ASSERT(regExpObjectNode);
                executeInsertionSet();
                for (unsigned otherNodeIndex = m_nodeIndex; otherNodeIndex--;) {
                    Node* otherNode = m_block->at(otherNodeIndex);
                    if (otherNode == regExpObjectNode) {
                        lastIndex = 0;
                        break;
                    }
                    if (otherNode->op() == SetRegExpObjectLastIndex
                        && otherNode->child1() == regExpObjectNode
                        && otherNode->child2()->isInt32Constant()
                        && otherNode->child2()->asInt32() >= 0) {
                        lastIndex = otherNode->child2()->asUInt32();
                        break;
                    }
                    if (writesOverlap(m_graph, otherNode, RegExpObject_lastIndex))
                        break;
                }
                if (lastIndex == UINT_MAX) {
                    if (verbose)
                        dataLog("Giving up because the last index is not known.\n");
                    break;
                }
            }
            if (!regExp->globalOrSticky())
                lastIndex = 0;

            auto foldToConstant = [&] {
                Node* stringNode = nullptr;
                if (m_node->op() == RegExpExecNonGlobalOrSticky)
                    stringNode = m_node->child2().node();
                else
                    stringNode = m_node->child3().node();

                // NOTE: This mostly already protects us from having the compiler execute a regexp
                // operation on a ginormous string by preventing us from getting our hands on ginormous
                // strings in the first place.
                String string = stringNode->tryGetString(m_graph);
                if (!string) {
                    if (verbose)
                        dataLog("Giving up because the string is unknown.\n");
                    return false;
                }

                FrozenValue* regExpFrozenValue = m_graph.freeze(regExp);

                // Refuse to do things with regular expressions that have a ginormous number of
                // subpatterns.
                unsigned ginormousNumberOfSubPatterns = 1000;
                if (regExp->numSubpatterns() > ginormousNumberOfSubPatterns) {
                    if (verbose)
                        dataLog("Giving up because of pattern limit.\n");
                    return false;
                }

                if ((m_node->op() == RegExpExec || m_node->op() == RegExpExecNonGlobalOrSticky) && regExp->hasNamedCaptures()) {
                    // FIXME: https://bugs.webkit.org/show_bug.cgi?id=176464
                    // Implement strength reduction optimization for named capture groups.
                    if (verbose)
                        dataLog("Giving up because of named capture groups.\n");
                    return false;
                }

                m_graph.watchpoints().addLazily(globalObject->havingABadTimeWatchpoint());

                Structure* structure = globalObject->regExpMatchesArrayStructure();
                if (structure->indexingType() != ArrayWithContiguous) {
                    // This is further protection against a race with haveABadTime.
                    if (verbose)
                        dataLog("Giving up because the structure has the wrong indexing type.\n");
                    return false;
                }
                m_graph.registerStructure(structure);

                FrozenValue* globalObjectFrozenValue = m_graph.freeze(globalObject);

                MatchResult result;
                Vector<int> ovector;
                // We have to call the kind of match function that the main thread would have called.
                // Otherwise, we might not have the desired Yarr code compiled, and the match will fail.
                if (m_node->op() == RegExpExec || m_node->op() == RegExpExecNonGlobalOrSticky) {
                    int position;
                    if (!regExp->matchConcurrently(vm(), string, lastIndex, position, ovector)) {
                        if (verbose)
                            dataLog("Giving up because match failed.\n");
                        return false;
                    }
                    result.start = position;
                    result.end = ovector[1];
                } else {
                    if (!regExp->matchConcurrently(vm(), string, lastIndex, result)) {
                        if (verbose)
                            dataLog("Giving up because match failed.\n");
                        return false;
                    }
                }

                // We've constant-folded the regexp. Now we're committed to replacing RegExpExec/Test.

                m_changed = true;

                NodeOrigin origin = m_node->origin;

                m_insertionSet.insertNode(
                    m_nodeIndex, SpecNone, Check, origin, m_node->children.justChecks());

                if (m_node->op() == RegExpExec || m_node->op() == RegExpExecNonGlobalOrSticky) {
                    if (result) {
                        RegisteredStructureSet* structureSet = m_graph.addStructureSet(structure);

                        // Create an array modeling the JS array that we will try to allocate. This is
                        // basically createRegExpMatchesArray but over C++ strings instead of JSStrings.
                        Vector<String> resultArray;
                        resultArray.append(string.substring(result.start, result.end - result.start));
                        for (unsigned i = 1; i <= regExp->numSubpatterns(); ++i) {
                            int start = ovector[2 * i];
                            if (start >= 0)
                                resultArray.append(string.substring(start, ovector[2 * i + 1] - start));
                            else
                                resultArray.append(String());
                        }

                        unsigned publicLength = resultArray.size();
                        unsigned vectorLength =
                            Butterfly::optimalContiguousVectorLength(structure, publicLength);

                        UniquedStringImpl* indexUID = vm().propertyNames->index.impl();
                        UniquedStringImpl* inputUID = vm().propertyNames->input.impl();
                        UniquedStringImpl* groupsUID = vm().propertyNames->groups.impl();
                        unsigned indexIndex = m_graph.identifiers().ensure(indexUID);
                        unsigned inputIndex = m_graph.identifiers().ensure(inputUID);
                        unsigned groupsIndex = m_graph.identifiers().ensure(groupsUID);

                        unsigned firstChild = m_graph.m_varArgChildren.size();
                        m_graph.m_varArgChildren.append(
                            m_insertionSet.insertConstantForUse(
                                m_nodeIndex, origin, structure, KnownCellUse));
                        ObjectMaterializationData* data = m_graph.m_objectMaterializationData.add();

                        m_graph.m_varArgChildren.append(
                            m_insertionSet.insertConstantForUse(
                                m_nodeIndex, origin, jsNumber(publicLength), KnownInt32Use));
                        data->m_properties.append(PublicLengthPLoc);

                        m_graph.m_varArgChildren.append(
                            m_insertionSet.insertConstantForUse(
                                m_nodeIndex, origin, jsNumber(vectorLength), KnownInt32Use));
                        data->m_properties.append(VectorLengthPLoc);

                        m_graph.m_varArgChildren.append(
                            m_insertionSet.insertConstantForUse(
                                m_nodeIndex, origin, jsNumber(result.start), UntypedUse));
                        data->m_properties.append(
                            PromotedLocationDescriptor(NamedPropertyPLoc, indexIndex));

                        m_graph.m_varArgChildren.append(Edge(stringNode, UntypedUse));
                        data->m_properties.append(
                            PromotedLocationDescriptor(NamedPropertyPLoc, inputIndex));

                        // FIXME: https://bugs.webkit.org/show_bug.cgi?id=176464
                        // Implement strength reduction optimization for named capture groups.
                        m_graph.m_varArgChildren.append(
                            m_insertionSet.insertConstantForUse(
                                m_nodeIndex, origin, jsUndefined(), UntypedUse));
                        data->m_properties.append(
                            PromotedLocationDescriptor(NamedPropertyPLoc, groupsIndex));

                        auto materializeString = [&] (const String& string) -> Node* {
                            if (string.isNull())
                                return nullptr;
                            if (string.isEmpty()) {
                                return m_insertionSet.insertConstant(
                                    m_nodeIndex, origin, vm().smallStrings.emptyString());
                            }
                            LazyJSValue value = LazyJSValue::newString(m_graph, string);
                            return m_insertionSet.insertNode(
                                m_nodeIndex, SpecNone, LazyJSConstant, origin,
                                OpInfo(m_graph.m_lazyJSValues.add(value)));
                        };

                        for (unsigned i = 0; i < resultArray.size(); ++i) {
                            if (Node* node = materializeString(resultArray[i])) {
                                m_graph.m_varArgChildren.append(Edge(node, UntypedUse));
                                data->m_properties.append(
                                    PromotedLocationDescriptor(IndexedPropertyPLoc, i));
                            }
                        }

                        Node* resultNode = m_insertionSet.insertNode(
                            m_nodeIndex, SpecArray, Node::VarArg, MaterializeNewObject, origin,
                            OpInfo(structureSet), OpInfo(data), firstChild,
                            m_graph.m_varArgChildren.size() - firstChild);

                        m_node->convertToIdentityOn(resultNode);
                    } else
                        m_graph.convertToConstant(m_node, jsNull());
                } else
                    m_graph.convertToConstant(m_node, jsBoolean(!!result));

                // Whether it's Exec or Test, we need to tell the globalObject and RegExpObject what's up.
                // Because SetRegExpObjectLastIndex may exit and it clobbers exit state, we do that
                // first.

                if (regExp->globalOrSticky()) {
                    ASSERT(regExpObjectNode);
                    m_insertionSet.insertNode(
                        m_nodeIndex, SpecNone, SetRegExpObjectLastIndex, origin,
                        OpInfo(false),
                        Edge(regExpObjectNode, RegExpObjectUse),
                        m_insertionSet.insertConstantForUse(
                            m_nodeIndex, origin, jsNumber(result ? result.end : 0), UntypedUse));

                    origin = origin.withInvalidExit();
                }

                if (result) {
                    unsigned firstChild = m_graph.m_varArgChildren.size();
                    m_graph.m_varArgChildren.append(
                        m_insertionSet.insertConstantForUse(
                            m_nodeIndex, origin, globalObjectFrozenValue, KnownCellUse));
                    m_graph.m_varArgChildren.append(
                        m_insertionSet.insertConstantForUse(
                            m_nodeIndex, origin, regExpFrozenValue, KnownCellUse));
                    m_graph.m_varArgChildren.append(Edge(stringNode, KnownCellUse));
                    m_graph.m_varArgChildren.append(
                        m_insertionSet.insertConstantForUse(
                            m_nodeIndex, origin, jsNumber(result.start), KnownInt32Use));
                    m_graph.m_varArgChildren.append(
                        m_insertionSet.insertConstantForUse(
                            m_nodeIndex, origin, jsNumber(result.end), KnownInt32Use));
                    m_insertionSet.insertNode(
                        m_nodeIndex, SpecNone, Node::VarArg, RecordRegExpCachedResult, origin,
                        OpInfo(), OpInfo(), firstChild, m_graph.m_varArgChildren.size() - firstChild);

                    origin = origin.withInvalidExit();
                }

                m_node->origin = origin;
                return true;
            };

            auto convertToStatic = [&] {
                if (m_node->op() != RegExpExec)
                    return false;
                if (regExp->globalOrSticky())
                    return false;
                if (m_node->child3().useKind() != StringUse)
                    return false;
                NodeOrigin origin = m_node->origin;
                m_insertionSet.insertNode(
                    m_nodeIndex, SpecNone, Check, origin, m_node->children.justChecks());
                m_node->convertToRegExpExecNonGlobalOrStickyWithoutChecks(m_graph.freeze(regExp));
                m_changed = true;
                return true;
            };

            if (foldToConstant())
                break;

            if (convertToStatic())
                break;

            break;
        }

        case StringReplace:
        case StringReplaceRegExp: {
            Node* stringNode = m_node->child1().node();
            String string = stringNode->tryGetString(m_graph);
            if (!string)
                break;
            
            Node* regExpObjectNode = m_node->child2().node();
            RegExp* regExp;
            if (RegExpObject* regExpObject = regExpObjectNode->dynamicCastConstant<RegExpObject*>(vm()))
                regExp = regExpObject->regExp();
            else if (regExpObjectNode->op() == NewRegexp)
                regExp = regExpObjectNode->castOperand<RegExp*>();
            else {
                if (verbose)
                    dataLog("Giving up because the regexp is unknown.\n");
                break;
            }

            String replace = m_node->child3()->tryGetString(m_graph);
            if (!replace)
                break;

            StringBuilder builder;

            unsigned lastIndex = 0;
            unsigned startPosition = 0;
            bool ok = true;
            do {
                MatchResult result;
                Vector<int> ovector;
                // Model which version of match() is called by the main thread.
                if (replace.isEmpty() && regExp->global()) {
                    if (!regExp->matchConcurrently(vm(), string, startPosition, result)) {
                        ok = false;
                        break;
                    }
                } else {
                    int position;
                    if (!regExp->matchConcurrently(vm(), string, startPosition, position, ovector)) {
                        ok = false;
                        break;
                    }
                    
                    result.start = position;
                    result.end = ovector[1];
                }
                
                if (!result)
                    break;

                unsigned replLen = replace.length();
                if (lastIndex < result.start || replLen) {
                    builder.appendSubstring(string, lastIndex, result.start - lastIndex);
                    if (replLen) {
                        StringBuilder replacement;
                        substituteBackreferences(replacement, replace, string, ovector.data(), regExp);
                        builder.append(replacement);
                    }
                }

                lastIndex = result.end;
                startPosition = lastIndex;

                // special case of empty match
                if (result.empty()) {
                    startPosition++;
                    if (startPosition > string.length())
                        break;
                }
            } while (regExp->global());
            if (!ok)
                break;

            // We are committed at this point.
            m_changed = true;

            NodeOrigin origin = m_node->origin;

            // Preserve any checks we have.
            m_insertionSet.insertNode(
                m_nodeIndex, SpecNone, Check, origin, m_node->children.justChecks());

            if (regExp->global()) {
                m_insertionSet.insertNode(
                    m_nodeIndex, SpecNone, SetRegExpObjectLastIndex, origin,
                    OpInfo(false),
                    Edge(regExpObjectNode, RegExpObjectUse),
                    m_insertionSet.insertConstantForUse(
                        m_nodeIndex, origin, jsNumber(0), UntypedUse));
                
                origin = origin.withInvalidExit();
            }

            if (!lastIndex && builder.isEmpty())
                m_node->convertToIdentityOn(stringNode);
            else {
                builder.appendSubstring(string, lastIndex);
                m_node->convertToLazyJSConstant(m_graph, LazyJSValue::newString(m_graph, builder.toString()));
            }

            m_node->origin = origin;
            break;
        }
            
        case Call:
        case Construct:
        case TailCallInlinedCaller:
        case TailCall: {
            ExecutableBase* executable = nullptr;
            Edge callee = m_graph.varArgChild(m_node, 0);
            CallVariant callVariant;
            if (JSFunction* function = callee->dynamicCastConstant<JSFunction*>(vm())) {
                executable = function->executable();
                callVariant = CallVariant(function);
            } else if (callee->isFunctionAllocation()) {
                executable = callee->castOperand<FunctionExecutable*>();
                callVariant = CallVariant(executable);
            }
            
            if (!executable)
                break;
            
            if (FunctionExecutable* functionExecutable = jsDynamicCast<FunctionExecutable*>(vm(), executable)) {
                if (m_node->op() == Construct && functionExecutable->constructAbility() == ConstructAbility::CannotConstruct)
                    break;

                // We need to update m_parameterSlots before we get to the backend, but we don't
                // want to do too much of this.
                unsigned numAllocatedArgs =
                    static_cast<unsigned>(functionExecutable->parameterCount()) + 1;
                
                if (numAllocatedArgs <= Options::maximumDirectCallStackSize()) {
                    m_graph.m_parameterSlots = std::max(
                        m_graph.m_parameterSlots,
                        Graph::parameterSlotsForArgCount(numAllocatedArgs));
                }
            }

            m_graph.m_plan.recordedStatuses().addCallLinkStatus(m_node->origin.semantic, CallLinkStatus(callVariant));

            m_node->convertToDirectCall(m_graph.freeze(executable));
            m_changed = true;
            break;
        }

        default:
            break;
        }
    }
            
    void convertToIdentityOverChild(unsigned childIndex)
    {
        ASSERT(!(m_node->flags() & NodeHasVarArgs));
        m_insertionSet.insertCheck(m_graph, m_nodeIndex, m_node);
        m_node->children.removeEdge(childIndex ^ 1);
        m_node->convertToIdentity();
        m_changed = true;
    }
    
    void convertToIdentityOverChild1()
    {
        convertToIdentityOverChild(0);
    }
    
    void convertToIdentityOverChild2()
    {
        convertToIdentityOverChild(1);
    }

    void convertToLazyJSValue(Node* node, LazyJSValue value)
    {
        m_insertionSet.insertCheck(m_graph, m_nodeIndex, node);
        node->convertToLazyJSConstant(m_graph, value);
    }
    
    void handleCommutativity()
    {
        // It's definitely not sound to swap the lhs and rhs when we may be performing effectful
        // calls on the lhs/rhs for valueOf.
        if (m_node->child1().useKind() == UntypedUse || m_node->child2().useKind() == UntypedUse)
            return;

        // If the right side is a constant then there is nothing left to do.
        if (m_node->child2()->hasConstant())
            return;
        
        // This case ensures that optimizations that look for x + const don't also have
        // to look for const + x.
        if (m_node->child1()->hasConstant() && !m_node->child1()->asJSValue().isCell()) {
            std::swap(m_node->child1(), m_node->child2());
            m_changed = true;
            return;
        }
        
        // This case ensures that CSE is commutativity-aware.
        if (m_node->child1().node() > m_node->child2().node()) {
            std::swap(m_node->child1(), m_node->child2());
            m_changed = true;
            return;
        }
    }

    void executeInsertionSet()
    {
        m_nodeIndex += m_insertionSet.execute(m_block);
    }
    
    InsertionSet m_insertionSet;
    BasicBlock* m_block;
    unsigned m_nodeIndex;
    Node* m_node;
    bool m_changed;
};
    
bool performStrengthReduction(Graph& graph)
{
    return runPhase<StrengthReductionPhase>(graph);
}

} } // namespace JSC::DFG

#endif // ENABLE(DFG_JIT)

