/*
 * 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. 
 */

#include "config.h"
#include "PutByIdStatus.h"

#include "BytecodeStructs.h"
#include "CodeBlock.h"
#include "ComplexGetStatus.h"
#include "GetterSetterAccessCase.h"
#include "ICStatusUtils.h"
#include "PolymorphicAccess.h"
#include "StructureInlines.h"
#include "StructureStubInfo.h"
#include <wtf/ListDump.h>

namespace JSC {

bool PutByIdStatus::appendVariant(const PutByIdVariant& variant)
{
    return appendICStatusVariant(m_variants, variant);
}

PutByIdStatus PutByIdStatus::computeFromLLInt(CodeBlock* profiledBlock, BytecodeIndex bytecodeIndex, UniquedStringImpl* uid)
{
    VM& vm = profiledBlock->vm();
    
    auto instruction = profiledBlock->instructions().at(bytecodeIndex.offset());

    // We are not yet using `computeFromLLInt` in any place for `put_private_name`.
    // We can add support for it if this is required in future changes, since we have
    // IC implemented for this operation on LLInt.
    ASSERT(!instruction->is<OpPutPrivateName>());

    auto bytecode = instruction->as<OpPutById>();
    auto& metadata = bytecode.metadata(profiledBlock);

    StructureID structureID = metadata.m_oldStructureID;
    if (!structureID)
        return PutByIdStatus(NoInformation);
    
    Structure* structure = vm.heap.structureIDTable().get(structureID);

    StructureID newStructureID = metadata.m_newStructureID;
    if (!newStructureID) {
        PropertyOffset offset = structure->getConcurrently(uid);
        if (!isValidOffset(offset))
            return PutByIdStatus(NoInformation);
        
        return PutByIdVariant::replace(structure, offset);
    }

    Structure* newStructure = vm.heap.structureIDTable().get(newStructureID);
    
    ASSERT(structure->transitionWatchpointSetHasBeenInvalidated());
    
    PropertyOffset offset = newStructure->getConcurrently(uid);
    if (!isValidOffset(offset))
        return PutByIdStatus(NoInformation);
    
    ObjectPropertyConditionSet conditionSet;
    if (!(bytecode.m_flags.isDirect())) {
        conditionSet =
            generateConditionsForPropertySetterMissConcurrently(
                vm, profiledBlock->globalObject(), structure, uid);
        if (!conditionSet.isValid())
            return PutByIdStatus(NoInformation);
    }
    
    return PutByIdVariant::transition(
        structure, newStructure, conditionSet, offset);
}

#if ENABLE(JIT)
PutByIdStatus PutByIdStatus::computeFor(CodeBlock* profiledBlock, ICStatusMap& map, BytecodeIndex bytecodeIndex, UniquedStringImpl* uid, ExitFlag didExit, CallLinkStatus::ExitSiteData callExitSiteData)
{
    ConcurrentJSLocker locker(profiledBlock->m_lock);
    
    UNUSED_PARAM(profiledBlock);
    UNUSED_PARAM(bytecodeIndex);
    UNUSED_PARAM(uid);
#if ENABLE(DFG_JIT)
    if (didExit)
        return PutByIdStatus(TakesSlowPath);
    
    StructureStubInfo* stubInfo = map.get(CodeOrigin(bytecodeIndex)).stubInfo;
    PutByIdStatus result = computeForStubInfo(
        locker, profiledBlock, stubInfo, uid, callExitSiteData);
    if (!result)
        return computeFromLLInt(profiledBlock, bytecodeIndex, uid);
    
    return result;
#else // ENABLE(JIT)
    UNUSED_PARAM(map);
    UNUSED_PARAM(didExit);
    UNUSED_PARAM(callExitSiteData);
    return PutByIdStatus(NoInformation);
#endif // ENABLE(JIT)
}

PutByIdStatus PutByIdStatus::computeForStubInfo(const ConcurrentJSLocker& locker, CodeBlock* baselineBlock, StructureStubInfo* stubInfo, CodeOrigin codeOrigin, UniquedStringImpl* uid)
{
    return computeForStubInfo(
        locker, baselineBlock, stubInfo, uid,
        CallLinkStatus::computeExitSiteData(baselineBlock, codeOrigin.bytecodeIndex()));
}

PutByIdStatus PutByIdStatus::computeForStubInfo(
    const ConcurrentJSLocker& locker, CodeBlock* profiledBlock, StructureStubInfo* stubInfo,
    UniquedStringImpl* uid, CallLinkStatus::ExitSiteData callExitSiteData)
{
    StubInfoSummary summary = StructureStubInfo::summary(profiledBlock->vm(), stubInfo);
    if (!isInlineable(summary))
        return PutByIdStatus(summary);
    
    switch (stubInfo->cacheType()) {
    case CacheType::Unset:
        // This means that we attempted to cache but failed for some reason.
        return PutByIdStatus(JSC::slowVersion(summary));
        
    case CacheType::PutByIdReplace: {
        PropertyOffset offset =
            stubInfo->u.byIdSelf.baseObjectStructure->getConcurrently(uid);
        if (isValidOffset(offset)) {
            return PutByIdVariant::replace(
                stubInfo->u.byIdSelf.baseObjectStructure.get(), offset);
        }
        return PutByIdStatus(JSC::slowVersion(summary));
    }
        
    case CacheType::Stub: {
        PolymorphicAccess* list = stubInfo->u.stub;
        
        PutByIdStatus result;
        result.m_state = Simple;
        
        for (unsigned i = 0; i < list->size(); ++i) {
            const AccessCase& access = list->at(i);
            if (access.viaProxy())
                return PutByIdStatus(JSC::slowVersion(summary));
            if (access.usesPolyProto())
                return PutByIdStatus(JSC::slowVersion(summary));
            
            PutByIdVariant variant;
            
            switch (access.type()) {
            case AccessCase::Replace: {
                Structure* structure = access.structure();
                PropertyOffset offset = structure->getConcurrently(uid);
                if (!isValidOffset(offset))
                    return PutByIdStatus(JSC::slowVersion(summary));
                variant = PutByIdVariant::replace(
                    structure, offset);
                break;
            }
                
            case AccessCase::Transition: {
                PropertyOffset offset =
                    access.newStructure()->getConcurrently(uid);
                if (!isValidOffset(offset))
                    return PutByIdStatus(JSC::slowVersion(summary));
                ObjectPropertyConditionSet conditionSet = access.conditionSet();
                if (!conditionSet.structuresEnsureValidity())
                    return PutByIdStatus(JSC::slowVersion(summary));
                variant = PutByIdVariant::transition(
                    access.structure(), access.newStructure(), conditionSet, offset);
                break;
            }
                
            case AccessCase::Setter: {
                Structure* structure = access.structure();
                
                ComplexGetStatus complexGetStatus = ComplexGetStatus::computeFor(
                    structure, access.conditionSet(), uid);
                
                switch (complexGetStatus.kind()) {
                case ComplexGetStatus::ShouldSkip:
                    continue;
                    
                case ComplexGetStatus::TakesSlowPath:
                    return PutByIdStatus(JSC::slowVersion(summary));
                    
                case ComplexGetStatus::Inlineable: {
                    std::unique_ptr<CallLinkStatus> callLinkStatus =
                        makeUnique<CallLinkStatus>();
                    if (CallLinkInfo* callLinkInfo = access.as<GetterSetterAccessCase>().callLinkInfo()) {
                        *callLinkStatus = CallLinkStatus::computeFor(
                            locker, profiledBlock, *callLinkInfo, callExitSiteData);
                    }
                    
                    variant = PutByIdVariant::setter(
                        structure, complexGetStatus.offset(), complexGetStatus.conditionSet(),
                        WTFMove(callLinkStatus));
                } }
                break;
            }
                
            case AccessCase::CustomValueSetter:
            case AccessCase::CustomAccessorSetter:
                return PutByIdStatus(MakesCalls);

            default:
                return PutByIdStatus(JSC::slowVersion(summary));
            }
            
            if (!result.appendVariant(variant))
                return PutByIdStatus(JSC::slowVersion(summary));
        }
        
        return result;
    }
        
    default:
        return PutByIdStatus(JSC::slowVersion(summary));
    }
}

PutByIdStatus PutByIdStatus::computeFor(CodeBlock* baselineBlock, ICStatusMap& baselineMap, ICStatusContextStack& contextStack, CodeOrigin codeOrigin, UniquedStringImpl* uid)
{
    BytecodeIndex bytecodeIndex = codeOrigin.bytecodeIndex();
    CallLinkStatus::ExitSiteData callExitSiteData = CallLinkStatus::computeExitSiteData(baselineBlock, bytecodeIndex);
    ExitFlag didExit = hasBadCacheExitSite(baselineBlock, bytecodeIndex);

    for (ICStatusContext* context : contextStack) {
        ICStatus status = context->get(codeOrigin);
        
        auto bless = [&] (const PutByIdStatus& result) -> PutByIdStatus {
            if (!context->isInlined(codeOrigin)) {
                PutByIdStatus baselineResult = computeFor(
                    baselineBlock, baselineMap, bytecodeIndex, uid, didExit,
                    callExitSiteData);
                baselineResult.merge(result);
                return baselineResult;
            }
            if (didExit.isSet(ExitFromInlined))
                return result.slowVersion();
            return result;
        };
        
        if (status.stubInfo) {
            PutByIdStatus result;
            {
                ConcurrentJSLocker locker(context->optimizedCodeBlock->m_lock);
                result = computeForStubInfo(
                    locker, context->optimizedCodeBlock, status.stubInfo, uid, callExitSiteData);
            }
            if (result.isSet())
                return bless(result);
        }
        
        if (status.putStatus)
            return bless(*status.putStatus);
    }
    
    return computeFor(baselineBlock, baselineMap, bytecodeIndex, uid, didExit, callExitSiteData);
}

PutByIdStatus PutByIdStatus::computeFor(JSGlobalObject* globalObject, const StructureSet& set, UniquedStringImpl* uid, bool isDirect, PrivateFieldPutKind privateFieldPutKind)
{
    if (parseIndex(*uid))
        return PutByIdStatus(TakesSlowPath);

    if (set.isEmpty())
        return PutByIdStatus();
    
    VM& vm = globalObject->vm();
    PutByIdStatus result;
    result.m_state = Simple;
    for (unsigned i = 0; i < set.size(); ++i) {
        Structure* structure = set[i];
        
        if (structure->typeInfo().overridesGetOwnPropertySlot() && structure->typeInfo().type() != GlobalObjectType)
            return PutByIdStatus(TakesSlowPath);

        if (!structure->propertyAccessesAreCacheable())
            return PutByIdStatus(TakesSlowPath);
    
        unsigned attributes;
        PropertyOffset offset = structure->getConcurrently(uid, attributes);
        if (isValidOffset(offset)) {
            // We can't have a valid offset for structures on `PutPrivateNameById` define mode
            // since it means we are redefining a private field. In such case, we need to take 
            // slow path to throw exception.
            if (privateFieldPutKind.isDefine())
                return PutByIdStatus(TakesSlowPath);

            if (attributes & PropertyAttribute::CustomAccessorOrValue)
                return PutByIdStatus(MakesCalls);

            if (attributes & (PropertyAttribute::Accessor | PropertyAttribute::ReadOnly))
                return PutByIdStatus(TakesSlowPath);
            
            WatchpointSet* replaceSet = structure->propertyReplacementWatchpointSet(offset);
            if (!replaceSet || replaceSet->isStillValid()) {
                // When this executes, it'll create, and fire, this replacement watchpoint set.
                // That means that  this has probably never executed or that something fishy is
                // going on. Also, we cannot create or fire the watchpoint set from the concurrent
                // JIT thread, so even if we wanted to do this, we'd need to have a lazy thingy.
                // So, better leave this alone and take slow path.
                return PutByIdStatus(TakesSlowPath);
            }

            PutByIdVariant variant =
                PutByIdVariant::replace(structure, offset);
            if (!result.appendVariant(variant))
                return PutByIdStatus(TakesSlowPath);
            continue;
        }

        // We can have a case with PutPrivateNameById in set mode and it
        // should never cause a structure transition because it means we are
        // trying to store in a not installed private field. We need to take
        // slow path to throw excpetion if it ever gets executed.
        if (privateFieldPutKind.isSet())
            return PutByIdStatus(TakesSlowPath);

        // Our hypothesis is that we're doing a transition. Before we prove that this is really
        // true, we want to do some sanity checks.
    
        // Don't cache put transitions on dictionaries.
        if (structure->isDictionary())
            return PutByIdStatus(TakesSlowPath);

        // If the structure corresponds to something that isn't an object, then give up, since
        // we don't want to be adding properties to strings.
        if (!structure->typeInfo().isObject())
            return PutByIdStatus(TakesSlowPath);
    
        ObjectPropertyConditionSet conditionSet;
        if (!isDirect) {
            ASSERT(privateFieldPutKind.isNone());
            conditionSet = generateConditionsForPropertySetterMissConcurrently(
                vm, globalObject, structure, uid);
            if (!conditionSet.isValid())
                return PutByIdStatus(TakesSlowPath);
        }
    
        // We only optimize if there is already a structure that the transition is cached to.
        Structure* transition =
            Structure::addPropertyTransitionToExistingStructureConcurrently(structure, uid, 0, offset);
        if (!transition)
            return PutByIdStatus(TakesSlowPath);
        ASSERT(isValidOffset(offset));
    
        bool didAppend = result.appendVariant(
            PutByIdVariant::transition(
                structure, transition, conditionSet, offset));
        if (!didAppend)
            return PutByIdStatus(TakesSlowPath);
    }
    
    return result;
}
#endif

bool PutByIdStatus::makesCalls() const
{
    if (m_state == MakesCalls)
        return true;
    
    if (m_state != Simple)
        return false;
    
    for (unsigned i = m_variants.size(); i--;) {
        if (m_variants[i].makesCalls())
            return true;
    }
    
    return false;
}

PutByIdStatus PutByIdStatus::slowVersion() const
{
    return PutByIdStatus(makesCalls() ? MakesCalls : TakesSlowPath);
}

void PutByIdStatus::markIfCheap(SlotVisitor& visitor)
{
    for (PutByIdVariant& variant : m_variants)
        variant.markIfCheap(visitor);
}

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

void PutByIdStatus::merge(const PutByIdStatus& other)
{
    if (other.m_state == NoInformation)
        return;
    
    auto mergeSlow = [&] () {
        *this = PutByIdStatus((makesCalls() || other.makesCalls()) ? MakesCalls : TakesSlowPath);
    };
    
    switch (m_state) {
    case NoInformation:
        *this = other;
        return;
        
    case Simple:
        if (other.m_state != Simple)
            return mergeSlow();
        
        for (const PutByIdVariant& other : other.m_variants) {
            if (!appendVariant(other))
                return mergeSlow();
        }
        return;
        
    case TakesSlowPath:
    case MakesCalls:
        return mergeSlow();
    }
    
    RELEASE_ASSERT_NOT_REACHED();
}

void PutByIdStatus::filter(const StructureSet& set)
{
    if (m_state != Simple)
        return;
    filterICStatusVariants(m_variants, set);
    for (PutByIdVariant& variant : m_variants)
        variant.fixTransitionToReplaceIfNecessary();
    if (m_variants.isEmpty())
        m_state = NoInformation;
}

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

} // namespace JSC

