/*
 * Copyright (C) 2013-2021 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. AND ITS CONTRIBUTORS ``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 ITS 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 "StructureRareData.h"

#include "AdaptiveInferredPropertyValueWatchpointBase.h"
#include "CachedSpecialPropertyAdaptiveStructureWatchpoint.h"
#include "JSImmutableButterfly.h"
#include "JSObjectInlines.h"
#include "JSPropertyNameEnumerator.h"
#include "JSString.h"
#include "ObjectPropertyConditionSet.h"
#include "StructureChain.h"
#include "StructureInlines.h"
#include "StructureRareDataInlines.h"

namespace JSC {

const ClassInfo StructureRareData::s_info = { "StructureRareData"_s, nullptr, nullptr, nullptr, CREATE_METHOD_TABLE(StructureRareData) };

Structure* StructureRareData::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
{
    return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info());
}

StructureRareData* StructureRareData::create(VM& vm, Structure* previous)
{
    StructureRareData* rareData = new (NotNull, allocateCell<StructureRareData>(vm)) StructureRareData(vm, previous);
    rareData->finishCreation(vm);
    return rareData;
}

void StructureRareData::destroy(JSCell* cell)
{
    static_cast<StructureRareData*>(cell)->StructureRareData::~StructureRareData();
}

StructureRareData::StructureRareData(VM& vm, Structure* previous)
    : JSCell(vm, vm.structureRareDataStructure.get())
    , m_previous(vm, this, previous, WriteBarrierStructureID::MayBeNull)
    , m_maxOffset(invalidOffset)
    , m_transitionOffset(invalidOffset)
{
}

template<typename Visitor>
void StructureRareData::visitChildrenImpl(JSCell* cell, Visitor& visitor)
{
    StructureRareData* thisObject = jsCast<StructureRareData*>(cell);
    ASSERT_GC_OBJECT_INHERITS(thisObject, info());

    Base::visitChildren(thisObject, visitor);
    visitor.append(thisObject->m_previous);
    if (thisObject->m_specialPropertyCache) {
        for (unsigned index = 0; index < numberOfCachedSpecialPropertyKeys; ++index)
            visitor.appendUnbarriered(thisObject->cachedSpecialProperty(static_cast<CachedSpecialPropertyKey>(index)));
    }
    visitor.appendUnbarriered(thisObject->cachedPropertyNameEnumerator());
    for (unsigned index = 0; index < numberOfCachedPropertyNames; ++index) {
        auto* cached = thisObject->m_cachedPropertyNames[index].unvalidatedGet();
        if (cached != cachedPropertyNamesSentinel())
            visitor.appendUnbarriered(cached);
    }
}

DEFINE_VISIT_CHILDREN(StructureRareData);

// ----------- Cached special properties helper watchpoint classes -----------

class CachedSpecialPropertyAdaptiveInferredPropertyValueWatchpoint final : public AdaptiveInferredPropertyValueWatchpointBase {
public:
    typedef AdaptiveInferredPropertyValueWatchpointBase Base;
    CachedSpecialPropertyAdaptiveInferredPropertyValueWatchpoint(const ObjectPropertyCondition&, StructureRareData*);

private:
    bool isValid() const final;
    void handleFire(VM&, const FireDetail&) final;

    StructureRareData* m_structureRareData;
};

SpecialPropertyCacheEntry::~SpecialPropertyCacheEntry() = default;

SpecialPropertyCache& StructureRareData::ensureSpecialPropertyCacheSlow()
{
    ASSERT(!isCompilationThread() && !Thread::mayBeGCThread());
    ASSERT(!m_specialPropertyCache);
    auto cache = makeUnique<SpecialPropertyCache>();
    WTF::storeStoreFence(); // Expose valid struct for concurrent threads including concurrent compilers.
    m_specialPropertyCache = WTFMove(cache);
    return *m_specialPropertyCache.get();
}

inline void StructureRareData::giveUpOnSpecialPropertyCache(CachedSpecialPropertyKey key)
{
    ensureSpecialPropertyCache().m_cache[static_cast<unsigned>(key)].m_value.setWithoutWriteBarrier(JSCell::seenMultipleCalleeObjects());
}

void StructureRareData::cacheSpecialPropertySlow(JSGlobalObject* globalObject, VM& vm, Structure* ownStructure, JSValue value, CachedSpecialPropertyKey key, const PropertySlot& slot)
{
    UniquedStringImpl* uid = nullptr;
    switch (key) {
    case CachedSpecialPropertyKey::ToStringTag:
        uid = vm.propertyNames->toStringTagSymbol.impl();
        break;
    case CachedSpecialPropertyKey::ToString:
        uid = vm.propertyNames->toString.impl();
        break;
    case CachedSpecialPropertyKey::ValueOf:
        uid = vm.propertyNames->valueOf.impl();
        break;
    case CachedSpecialPropertyKey::ToPrimitive:
        uid = vm.propertyNames->toPrimitiveSymbol.impl();
        break;
    case CachedSpecialPropertyKey::ToJSON:
        uid = vm.propertyNames->toJSON.impl();
        break;
    }

    if (!ownStructure->propertyAccessesAreCacheable() || ownStructure->isProxy()) {
        giveUpOnSpecialPropertyCache(key);
        return;
    }

    ObjectPropertyConditionSet conditionSet;
    if (slot.isValue()) {
        // We don't handle the own property case of special properties (toString, valueOf, @@toPrimitive, @@toStringTag) because we would never know if a new
        // object transitioning to the same structure had the same value stored in that property.
        // Additionally, this is a super unlikely case anyway.
        if (!slot.isCacheable() || slot.slotBase()->structure() == ownStructure)
            return;

        // This will not create a condition for the current structure but that is good because we know that property
        // is not on the ownStructure so we will transisition if one is added and this cache will no longer be used.
        auto cacheStatus = prepareChainForCaching(globalObject, ownStructure, slot.slotBase());
        if (!cacheStatus) {
            giveUpOnSpecialPropertyCache(key);
            return;
        }
        conditionSet = generateConditionsForPrototypePropertyHit(vm, this, globalObject, ownStructure, slot.slotBase(), uid);
        ASSERT(!conditionSet.isValid() || conditionSet.hasOneSlotBaseCondition());
    } else if (slot.isUnset()) {
        if (!ownStructure->propertyAccessesAreCacheableForAbsence()) {
            giveUpOnSpecialPropertyCache(key);
            return;
        }

        auto cacheStatus = prepareChainForCaching(globalObject, ownStructure, nullptr);
        if (!cacheStatus) {
            giveUpOnSpecialPropertyCache(key);
            return;
        }
        conditionSet = generateConditionsForPropertyMiss(vm, this, globalObject, ownStructure, uid);
    } else
        return;

    if (!conditionSet.isValid()) {
        giveUpOnSpecialPropertyCache(key);
        return;
    }

    ObjectPropertyCondition equivCondition;
    for (const ObjectPropertyCondition& condition : conditionSet) {
        if (condition.condition().kind() == PropertyCondition::Presence) {
            ASSERT(isValidOffset(condition.offset()));
            condition.object()->structure()->startWatchingPropertyForReplacements(vm, condition.offset());
            equivCondition = condition.attemptToMakeEquivalenceWithoutBarrier();

            // The equivalence condition won't be watchable if we have already seen a replacement.
            if (!equivCondition.isWatchable(PropertyCondition::MakeNoChanges)) {
                giveUpOnSpecialPropertyCache(key);
                return;
            }
        } else if (!condition.isWatchable(PropertyCondition::MakeNoChanges)) {
            giveUpOnSpecialPropertyCache(key);
            return;
        }
    }

    ASSERT(conditionSet.structuresEnsureValidity());
    auto& cache = ensureSpecialPropertyCache().m_cache[static_cast<unsigned>(key)];
    for (ObjectPropertyCondition condition : conditionSet) {
        if (condition.condition().kind() == PropertyCondition::Presence) {
            cache.m_equivalenceWatchpoint = makeUnique<CachedSpecialPropertyAdaptiveInferredPropertyValueWatchpoint>(equivCondition, this);
            cache.m_equivalenceWatchpoint->install(vm);
        } else
            cache.m_missWatchpoints.add(condition, this)->install(vm);
    }
    cache.m_value.set(vm, this, value);
}

void StructureRareData::clearCachedSpecialProperty(CachedSpecialPropertyKey key)
{
    auto* objectToStringCache = m_specialPropertyCache.get();
    if (!objectToStringCache)
        return;
    auto& cache = objectToStringCache->m_cache[static_cast<unsigned>(key)];
    cache.m_missWatchpoints.clear();
    cache.m_equivalenceWatchpoint.reset();
    if (cache.m_value.get() != JSCell::seenMultipleCalleeObjects())
        cache.m_value.clear();
}

void StructureRareData::finalizeUnconditionally(VM& vm)
{
    if (m_specialPropertyCache) {
        auto clearCacheIfInvalidated = [&](CachedSpecialPropertyKey key) {
            auto& cache = m_specialPropertyCache->m_cache[static_cast<unsigned>(key)];
            if (cache.m_equivalenceWatchpoint) {
                if (!cache.m_equivalenceWatchpoint->key().isStillLive(vm)) {
                    clearCachedSpecialProperty(key);
                    return;
                }
            }
            for (auto* watchpoint : cache.m_missWatchpoints) {
                if (!watchpoint->key().isStillLive(vm)) {
                    clearCachedSpecialProperty(key);
                    return;
                }
            }
        };

        for (unsigned index = 0; index < numberOfCachedSpecialPropertyKeys; ++index)
            clearCacheIfInvalidated(static_cast<CachedSpecialPropertyKey>(index));
    }
}

// ------------- Methods for Object.prototype.toString() helper watchpoint classes --------------

CachedSpecialPropertyAdaptiveInferredPropertyValueWatchpoint::CachedSpecialPropertyAdaptiveInferredPropertyValueWatchpoint(const ObjectPropertyCondition& key, StructureRareData* structureRareData)
    : Base(key)
    , m_structureRareData(structureRareData)
{
}

bool CachedSpecialPropertyAdaptiveInferredPropertyValueWatchpoint::isValid() const
{
    return m_structureRareData->isLive();
}

void CachedSpecialPropertyAdaptiveInferredPropertyValueWatchpoint::handleFire(VM& vm, const FireDetail&)
{
    CachedSpecialPropertyKey key = CachedSpecialPropertyKey::ToStringTag;
    if (this->key().uid() == vm.propertyNames->toStringTagSymbol.impl())
        key = CachedSpecialPropertyKey::ToStringTag;
    else if (this->key().uid() == vm.propertyNames->toString.impl())
        key = CachedSpecialPropertyKey::ToString;
    else if (this->key().uid() == vm.propertyNames->valueOf.impl())
        key = CachedSpecialPropertyKey::ValueOf;
    else if (this->key().uid() == vm.propertyNames->toJSON.impl())
        key = CachedSpecialPropertyKey::ToJSON;
    else {
        ASSERT(this->key().uid() == vm.propertyNames->toPrimitiveSymbol.impl());
        key = CachedSpecialPropertyKey::ToPrimitive;
    }
    m_structureRareData->clearCachedSpecialProperty(key);
}

} // namespace JSC
