/*
 * Copyright (C) 2012-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. 
 */

#pragma once

#include "CallLinkStatus.h"
#include "CodeOrigin.h"
#include "ConcurrentJSLock.h"
#include "ExitFlag.h"
#include "GetByIdVariant.h"
#include "ICStatusMap.h"
#include "ScopeOffset.h"
#include "StubInfoSummary.h"

namespace JSC {

class AccessCase;
class CodeBlock;
class JSModuleEnvironment;
class JSModuleNamespaceObject;
class ModuleNamespaceAccessCase;
class StructureStubInfo;

class GetByStatus final {
    WTF_MAKE_FAST_ALLOCATED;
public:
    enum State : uint8_t {
        // It's uncached so we have no information.
        NoInformation,
        // It's cached for a simple access to a known object property with
        // a possible structure chain and a possible specific value.
        Simple,
        // It's cached for a custom accessor with a possible structure chain.
        Custom,
        // It's cached for an access to a module namespace object's binding.
        ModuleNamespace,
        // It will likely take the slow path.
        LikelyTakesSlowPath,
        // It's known to take slow path. We also observed that the slow path was taken on StructureStubInfo.
        ObservedTakesSlowPath,
        // It will likely take the slow path and will make calls.
        MakesCalls,
        // It known to take paths that make calls. We also observed that the slow path was taken on StructureStubInfo.
        ObservedSlowPathAndMakesCalls ,
    };

    enum class TrackIdentifiers : uint8_t {
        No,  // Used for get_by_id
        Yes, // Used for get_by_val
    };

    GetByStatus()
        : m_state(NoInformation)
    {
    }
    
    explicit GetByStatus(State state)
        : m_state(state)
    {
        ASSERT(state == NoInformation || state == LikelyTakesSlowPath || state == ObservedTakesSlowPath || state == MakesCalls || state == ObservedSlowPathAndMakesCalls);
    }
    
    explicit GetByStatus(StubInfoSummary, StructureStubInfo&);
    
    GetByStatus(
        State state, bool wasSeenInJIT)
        : m_state(state)
        , m_wasSeenInJIT(wasSeenInJIT)
    {
    }

    // If we use a Box<Identifier> in the compiler thread, we need to keep the
    // Identifier alive and only deref it in the mutator thread later. This
    // ensures that the compiler thread doesn't race against the mutator in
    // adjusting the Identifier's refCount.
    using IdentifierKeepAlive = std::function<void(Box<Identifier>)>;

    static GetByStatus computeFor(CodeBlock* baselineBlock, ICStatusMap& baselineMap, ICStatusContextStack& dfgContextStack, CodeOrigin, TrackIdentifiers, IdentifierKeepAlive&);
    static GetByStatus computeFor(const StructureSet&, UniquedStringImpl*);

    State state() const { return m_state; }
    
    bool isSet() const { return m_state != NoInformation; }
    explicit operator bool() const { return isSet(); }
    bool isSimple() const { return m_state == Simple; }
    bool isCustom() const { return m_state == Custom; }
    bool isModuleNamespace() const { return m_state == ModuleNamespace; }

    size_t numVariants() const { return m_variants.size(); }
    const Vector<GetByIdVariant, 1>& variants() const { return m_variants; }
    const GetByIdVariant& at(size_t index) const { return m_variants[index]; }
    const GetByIdVariant& operator[](size_t index) const { return at(index); }

    bool takesSlowPath() const { return m_state == LikelyTakesSlowPath || m_state == ObservedTakesSlowPath || m_state == MakesCalls || m_state == ObservedSlowPathAndMakesCalls || m_state == Custom || m_state == ModuleNamespace; }
    bool observedStructureStubInfoSlowPath() const { return m_state == ObservedTakesSlowPath || m_state == ObservedSlowPathAndMakesCalls; }
    bool makesCalls() const;
    
    GetByStatus slowVersion() const;
    
    bool wasSeenInJIT() const { return m_wasSeenInJIT; }
    
    // Attempts to reduce the set of variants to fit the given structure set. This may be approximate.
    void filter(const StructureSet&);

    JSModuleNamespaceObject* moduleNamespaceObject() const { return m_moduleNamespaceData->m_moduleNamespaceObject; }
    JSModuleEnvironment* moduleEnvironment() const { return m_moduleNamespaceData->m_moduleEnvironment; }
    ScopeOffset scopeOffset() const { return m_moduleNamespaceData->m_scopeOffset; }
    
    void markIfCheap(SlotVisitor&);
    bool finalize(VM&); // Return true if this gets to live.

    bool appendVariant(const GetByIdVariant&);

    void dump(PrintStream&) const;

    Box<Identifier> singleIdentifier() const;
    
private:
    void merge(const GetByStatus&);
    
#if ENABLE(JIT)
    GetByStatus(const ModuleNamespaceAccessCase&);
    static GetByStatus computeForStubInfoWithoutExitSiteFeedback(
        const ConcurrentJSLocker&, CodeBlock* profiledBlock, StructureStubInfo*, CallLinkStatus::ExitSiteData, TrackIdentifiers, IdentifierKeepAlive&);
#endif
    static GetByStatus computeFromLLInt(CodeBlock*, BytecodeIndex, TrackIdentifiers);
    static GetByStatus computeFor(CodeBlock*, ICStatusMap&, BytecodeIndex, ExitFlag, CallLinkStatus::ExitSiteData, TrackIdentifiers, IdentifierKeepAlive&);

    struct ModuleNamespaceData {
        JSModuleNamespaceObject* m_moduleNamespaceObject { nullptr };
        JSModuleEnvironment* m_moduleEnvironment { nullptr };
        ScopeOffset m_scopeOffset { };
        Box<Identifier> m_identifier;
    };

    Vector<GetByIdVariant, 1> m_variants;
    Box<ModuleNamespaceData> m_moduleNamespaceData;
    State m_state;
    bool m_wasSeenInJIT { false };
};

} // namespace JSC
