/*
 * Copyright (C) 2014-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. ``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 "GetByVariant.h"

#include "CacheableIdentifierInlines.h"
#include "CallLinkStatus.h"
#include "JSFunctionInlines.h"

namespace JSC {

GetByVariant::GetByVariant(CacheableIdentifier identifier, const StructureSet& structureSet, PropertyOffset offset, const ObjectPropertyConditionSet& conditionSet, std::unique_ptr<CallLinkStatus> callLinkStatus, JSFunction* intrinsicFunction, FunctionPtr<CustomAccessorPtrTag> customAccessorGetter, std::unique_ptr<DOMAttributeAnnotation> domAttribute)
    : m_structureSet(structureSet)
    , m_conditionSet(conditionSet)
    , m_offset(offset)
    , m_callLinkStatus(WTFMove(callLinkStatus))
    , m_intrinsicFunction(intrinsicFunction)
    , m_customAccessorGetter(customAccessorGetter)
    , m_domAttribute(WTFMove(domAttribute))
    , m_identifier(WTFMove(identifier))
{
    if (!structureSet.size()) {
        ASSERT(offset == invalidOffset);
        ASSERT(conditionSet.isEmpty());
    }
    if (intrinsicFunction)
        ASSERT(intrinsic() != NoIntrinsic);
}

GetByVariant::~GetByVariant() { }

GetByVariant::GetByVariant(const GetByVariant& other)
    : GetByVariant(other.m_identifier)
{
    *this = other;
}

GetByVariant& GetByVariant::operator=(const GetByVariant& other)
{
    m_identifier = other.m_identifier;
    m_structureSet = other.m_structureSet;
    m_conditionSet = other.m_conditionSet;
    m_offset = other.m_offset;
    m_intrinsicFunction = other.m_intrinsicFunction;
    m_customAccessorGetter = other.m_customAccessorGetter;
    if (other.m_domAttribute)
        m_domAttribute = WTF::makeUnique<DOMAttributeAnnotation>(*other.m_domAttribute);
    else
        m_domAttribute = nullptr;
    if (other.m_callLinkStatus)
        m_callLinkStatus = makeUnique<CallLinkStatus>(*other.m_callLinkStatus);
    else
        m_callLinkStatus = nullptr;
    return *this;
}

inline bool GetByVariant::canMergeIntrinsicStructures(const GetByVariant& other) const
{
    if (m_intrinsicFunction != other.m_intrinsicFunction)
        return false;
    switch (intrinsic()) {
    case TypedArrayByteLengthIntrinsic: {
        // We can merge these sets as long as the element size of the two sets is the same.
        TypedArrayType thisType = (*m_structureSet.begin())->classInfoForCells()->typedArrayStorageType;
        TypedArrayType otherType = (*other.m_structureSet.begin())->classInfoForCells()->typedArrayStorageType;

        ASSERT(isTypedView(thisType) && isTypedView(otherType));

        return logElementSize(thisType) == logElementSize(otherType);
    }

    default:
        return true;
    }
    RELEASE_ASSERT_NOT_REACHED();
}

bool GetByVariant::attemptToMerge(const GetByVariant& other)
{
    if (!!m_identifier != !!other.m_identifier)
        return false;

    if (m_identifier && (m_identifier != other.m_identifier))
        return false;

    if (m_offset != other.m_offset)
        return false;
    
    if (m_callLinkStatus || other.m_callLinkStatus) {
        if (!(m_callLinkStatus && other.m_callLinkStatus))
            return false;
    }

    if (!canMergeIntrinsicStructures(other))
        return false;

    if (m_customAccessorGetter != other.m_customAccessorGetter)
        return false;

    if (m_domAttribute || other.m_domAttribute) {
        if (!(m_domAttribute && other.m_domAttribute))
            return false;
        if (*m_domAttribute != *other.m_domAttribute)
            return false;
    }

    if (m_conditionSet.isEmpty() != other.m_conditionSet.isEmpty())
        return false;
    
    ObjectPropertyConditionSet mergedConditionSet;
    if (!m_conditionSet.isEmpty()) {
        mergedConditionSet = m_conditionSet.mergedWith(other.m_conditionSet);
        if (!mergedConditionSet.isValid())
            return false;
        // If this is a hit variant, one slot base should exist. If this is not a hit variant, the slot base is not necessary.
        if (!isPropertyUnset() && !mergedConditionSet.hasOneSlotBaseCondition())
            return false;
    }
    m_conditionSet = mergedConditionSet;
    
    m_structureSet.merge(other.m_structureSet);
    
    if (m_callLinkStatus)
        m_callLinkStatus->merge(*other.m_callLinkStatus);

    return true;
}

template<typename Visitor>
void GetByVariant::visitAggregateImpl(Visitor& visitor)
{
    m_identifier.visitAggregate(visitor);
}

DEFINE_VISIT_AGGREGATE(GetByVariant);

template<typename Visitor>
void GetByVariant::markIfCheap(Visitor& visitor)
{
    m_structureSet.markIfCheap(visitor);
}

template void GetByVariant::markIfCheap(AbstractSlotVisitor&);
template void GetByVariant::markIfCheap(SlotVisitor&);

bool GetByVariant::finalize(VM& vm)
{
    if (!m_structureSet.isStillAlive(vm))
        return false;
    if (!m_conditionSet.areStillLive(vm))
        return false;
    if (m_callLinkStatus && !m_callLinkStatus->finalize(vm))
        return false;
    if (m_intrinsicFunction && !vm.heap.isMarked(m_intrinsicFunction))
        return false;
    return true;
}

void GetByVariant::dump(PrintStream& out) const
{
    dumpInContext(out, nullptr);
}

void GetByVariant::dumpInContext(PrintStream& out, DumpContext* context) const
{
    out.print("<");
    out.print("id='", m_identifier, "', ");
    if (!isSet()) {
        out.print("empty>");
        return;
    }
    out.print(inContext(structureSet(), context), ", ", inContext(m_conditionSet, context));
    out.print(", offset = ", offset());
    if (m_callLinkStatus)
        out.print(", call = ", *m_callLinkStatus);
    if (m_intrinsicFunction)
        out.print(", intrinsic = ", *m_intrinsicFunction);
    if (m_customAccessorGetter)
        out.print(", customaccessorgetter = ", RawPointer(m_customAccessorGetter.executableAddress()));
    if (m_domAttribute) {
        out.print(", domclass = ", RawPointer(m_domAttribute->classInfo));
        if (m_domAttribute->domJIT)
            out.print(", domjit = ", RawPointer(m_domAttribute->domJIT));
    }
    out.print(">");
}

} // namespace JSC

