/*
 * Copyright (C) 2018 Yusuke Suzuki <utatane.tea@gmail.com>.
 * Copyright (C) 2018 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 "InByIdStatus.h"

#include "CodeBlock.h"
#include "ComplexGetStatus.h"
#include "ICStatusUtils.h"
#include "JSCInlines.h"
#include "PolymorphicAccess.h"
#include "StructureStubInfo.h"
#include <wtf/ListDump.h>

namespace JSC {

bool InByIdStatus::appendVariant(const InByIdVariant& variant)
{
    return appendICStatusVariant(m_variants, variant);
}

#if ENABLE(JIT)
InByIdStatus InByIdStatus::computeFor(CodeBlock* profiledBlock, ICStatusMap& map, BytecodeIndex bytecodeIndex, UniquedStringImpl* uid, ExitFlag didExit)
{
    ConcurrentJSLocker locker(profiledBlock->m_lock);

    InByIdStatus result;

#if ENABLE(DFG_JIT)
    result = computeForStubInfoWithoutExitSiteFeedback(locker, map.get(CodeOrigin(bytecodeIndex)).stubInfo, uid);

    if (!result.takesSlowPath() && didExit)
        return InByIdStatus(TakesSlowPath);
#else
    UNUSED_PARAM(map);
    UNUSED_PARAM(bytecodeIndex);
    UNUSED_PARAM(uid);
    UNUSED_PARAM(didExit);
#endif

    return result;
}

InByIdStatus InByIdStatus::computeFor(CodeBlock* profiledBlock, ICStatusMap& map, BytecodeIndex bytecodeIndex, UniquedStringImpl* uid)
{
    return computeFor(profiledBlock, map, bytecodeIndex, uid, hasBadCacheExitSite(profiledBlock, bytecodeIndex));
}

InByIdStatus InByIdStatus::computeFor(
    CodeBlock* profiledBlock, ICStatusMap& baselineMap,
    ICStatusContextStack& contextStack, CodeOrigin codeOrigin, UniquedStringImpl* uid)
{
    BytecodeIndex bytecodeIndex = codeOrigin.bytecodeIndex();
    ExitFlag didExit = hasBadCacheExitSite(profiledBlock, bytecodeIndex);
    
    for (ICStatusContext* context : contextStack) {
        ICStatus status = context->get(codeOrigin);
        
        auto bless = [&] (const InByIdStatus& result) -> InByIdStatus {
            if (!context->isInlined(codeOrigin)) {
                InByIdStatus baselineResult = computeFor(
                    profiledBlock, baselineMap, bytecodeIndex, uid, didExit);
                baselineResult.merge(result);
                return baselineResult;
            }
            if (didExit.isSet(ExitFromInlined))
                return InByIdStatus(TakesSlowPath);
            return result;
        };
        
#if ENABLE(DFG_JIT)
        if (status.stubInfo) {
            InByIdStatus result;
            {
                ConcurrentJSLocker locker(context->optimizedCodeBlock->m_lock);
                result = computeForStubInfoWithoutExitSiteFeedback(locker, status.stubInfo, uid);
            }
            if (result.isSet())
                return bless(result);
        }
#endif
        
        if (status.inStatus)
            return bless(*status.inStatus);
    }
    
    return computeFor(profiledBlock, baselineMap, bytecodeIndex, uid, didExit);
}
#endif // ENABLE(JIT)

#if ENABLE(DFG_JIT)
InByIdStatus InByIdStatus::computeForStubInfo(const ConcurrentJSLocker& locker, CodeBlock* profiledBlock, StructureStubInfo* stubInfo, CodeOrigin codeOrigin, UniquedStringImpl* uid)
{
    InByIdStatus result = InByIdStatus::computeForStubInfoWithoutExitSiteFeedback(locker, stubInfo, uid);

    if (!result.takesSlowPath() && hasBadCacheExitSite(profiledBlock, codeOrigin.bytecodeIndex()))
        return InByIdStatus(TakesSlowPath);
    return result;
}

InByIdStatus InByIdStatus::computeForStubInfoWithoutExitSiteFeedback(const ConcurrentJSLocker&, StructureStubInfo* stubInfo, UniquedStringImpl* uid)
{
    StubInfoSummary summary = StructureStubInfo::summary(stubInfo);
    if (!isInlineable(summary))
        return InByIdStatus(summary);
    
    // Finally figure out if we can derive an access strategy.
    InByIdStatus result;
    result.m_state = Simple;
    switch (stubInfo->cacheType()) {
    case CacheType::Unset:
        return InByIdStatus(NoInformation);

    case CacheType::InByIdSelf: {
        Structure* structure = stubInfo->u.byIdSelf.baseObjectStructure.get();
        if (structure->takesSlowPathInDFGForImpureProperty())
            return InByIdStatus(TakesSlowPath);
        unsigned attributes;
        InByIdVariant variant;
        variant.m_offset = structure->getConcurrently(uid, attributes);
        if (!isValidOffset(variant.m_offset))
            return InByIdStatus(TakesSlowPath);
        if (attributes & PropertyAttribute::CustomAccessorOrValue)
            return InByIdStatus(TakesSlowPath);

        variant.m_structureSet.add(structure);
        bool didAppend = result.appendVariant(variant);
        ASSERT_UNUSED(didAppend, didAppend);
        return result;
    }

    case CacheType::Stub: {
        PolymorphicAccess* list = stubInfo->u.stub;
        for (unsigned listIndex = 0; listIndex < list->size(); ++listIndex) {
            const AccessCase& access = list->at(listIndex);
            if (access.viaProxy())
                return InByIdStatus(TakesSlowPath);

            if (access.usesPolyProto())
                return InByIdStatus(TakesSlowPath);

            Structure* structure = access.structure();
            if (!structure) {
                // The null structure cases arise due to array.length. We have no way of creating a
                // InByIdVariant for those, and we don't really have to since the DFG handles those
                // cases in FixupPhase using value profiling. That's a bit awkward - we shouldn't
                // have to use value profiling to discover something that the AccessCase could have
                // told us. But, it works well enough. So, our only concern here is to not
                // crash on null structure.
                return InByIdStatus(TakesSlowPath);
            }

            ComplexGetStatus complexGetStatus = ComplexGetStatus::computeFor(structure, access.conditionSet(), uid);
            switch (complexGetStatus.kind()) {
            case ComplexGetStatus::ShouldSkip:
                continue;

            case ComplexGetStatus::TakesSlowPath:
                return InByIdStatus(TakesSlowPath);

            case ComplexGetStatus::Inlineable: {
                switch (access.type()) {
                case AccessCase::InHit:
                case AccessCase::InMiss:
                    break;
                default:
                    return InByIdStatus(TakesSlowPath);
                }

                InByIdVariant variant(
                    StructureSet(structure), complexGetStatus.offset(),
                    complexGetStatus.conditionSet());

                if (!result.appendVariant(variant))
                    return InByIdStatus(TakesSlowPath);
                break;
            }
            }
        }

        return result;
    }

    default:
        return InByIdStatus(TakesSlowPath);
    }

    RELEASE_ASSERT_NOT_REACHED();
    return InByIdStatus();
}
#endif

void InByIdStatus::merge(const InByIdStatus& other)
{
    if (other.m_state == NoInformation)
        return;
    
    switch (m_state) {
    case NoInformation:
        *this = other;
        return;
        
    case Simple:
        if (other.m_state != Simple) {
            *this = InByIdStatus(TakesSlowPath);
            return;
        }
        for (const InByIdVariant& otherVariant : other.m_variants) {
            if (!appendVariant(otherVariant)) {
                *this = InByIdStatus(TakesSlowPath);
                return;
            }
        }
        return;
        
    case TakesSlowPath:
        return;
    }
    
    RELEASE_ASSERT_NOT_REACHED();
}

void InByIdStatus::filter(const StructureSet& structureSet)
{
    if (m_state != Simple)
        return;
    filterICStatusVariants(m_variants, structureSet);
    if (m_variants.isEmpty())
        m_state = NoInformation;
}

void InByIdStatus::markIfCheap(SlotVisitor& visitor)
{
    for (InByIdVariant& variant : m_variants)
        variant.markIfCheap(visitor);
}

bool InByIdStatus::finalize(VM& vm)
{
    for (InByIdVariant& variant : m_variants) {
        if (!variant.finalize(vm))
            return false;
    }
    return true;
}

void InByIdStatus::dump(PrintStream& out) const
{
    out.print("(");
    switch (m_state) {
    case NoInformation:
        out.print("NoInformation");
        break;
    case Simple:
        out.print("Simple");
        break;
    case TakesSlowPath:
        out.print("TakesSlowPath");
        break;
    }
    out.print(", ", listDump(m_variants), ")");
}

} // namespace JSC

