/*
 * Copyright (C) 2018-2020 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 "RecordedStatuses.h"

namespace JSC {

RecordedStatuses& RecordedStatuses::operator=(RecordedStatuses&& other)
{
    calls = WTFMove(other.calls);
    gets = WTFMove(other.gets);
    puts = WTFMove(other.puts);
    ins = WTFMove(other.ins);
    deletes = WTFMove(other.deletes);
    shrinkToFit();
    return *this;
}

RecordedStatuses::RecordedStatuses(RecordedStatuses&& other)
{
    *this = WTFMove(other);
}

CallLinkStatus* RecordedStatuses::addCallLinkStatus(const CodeOrigin& codeOrigin, const CallLinkStatus& status)
{
    auto statusPtr = makeUnique<CallLinkStatus>(status);
    CallLinkStatus* result = statusPtr.get();
    calls.append(std::make_pair(codeOrigin, WTFMove(statusPtr)));
    return result;
}

GetByStatus* RecordedStatuses::addGetByStatus(const CodeOrigin& codeOrigin, const GetByStatus& status)
{
    auto statusPtr = makeUnique<GetByStatus>(status);
    GetByStatus* result = statusPtr.get();
    gets.append(std::make_pair(codeOrigin, WTFMove(statusPtr)));
    return result;
}
    
PutByIdStatus* RecordedStatuses::addPutByIdStatus(const CodeOrigin& codeOrigin, const PutByIdStatus& status)
{
    auto statusPtr = makeUnique<PutByIdStatus>(status);
    PutByIdStatus* result = statusPtr.get();
    puts.append(std::make_pair(codeOrigin, WTFMove(statusPtr)));
    return result;
}

InByIdStatus* RecordedStatuses::addInByIdStatus(const CodeOrigin& codeOrigin, const InByIdStatus& status)
{
    auto statusPtr = makeUnique<InByIdStatus>(status);
    InByIdStatus* result = statusPtr.get();
    ins.append(std::make_pair(codeOrigin, WTFMove(statusPtr)));
    return result;
}

DeleteByStatus* RecordedStatuses::addDeleteByStatus(const CodeOrigin& codeOrigin, const DeleteByStatus& status)
{
    auto statusPtr = makeUnique<DeleteByStatus>(status);
    DeleteByStatus* result = statusPtr.get();
    deletes.append(std::make_pair(codeOrigin, WTFMove(statusPtr)));
    return result;
}

void RecordedStatuses::visitAggregate(SlotVisitor& slotVisitor)
{
    for (auto& pair : gets)
        pair.second->visitAggregate(slotVisitor);
    for (auto& pair : deletes)
        pair.second->visitAggregate(slotVisitor);
}

void RecordedStatuses::markIfCheap(SlotVisitor& slotVisitor)
{
    for (auto& pair : gets)
        pair.second->markIfCheap(slotVisitor);
    for (auto& pair : puts)
        pair.second->markIfCheap(slotVisitor);
    for (auto& pair : ins)
        pair.second->markIfCheap(slotVisitor);
    for (auto& pair : deletes)
        pair.second->markIfCheap(slotVisitor);
}

void RecordedStatuses::finalizeWithoutDeleting(VM& vm)
{
    // This variant of finalize gets called from within graph safepoints -- so there may be DFG IR in
    // some compiler thread that points to the statuses. That thread is stopped at a safepoint so
    // it's OK to edit its data structure, but it's not OK to delete them. Hence we don't remove
    // anything from the vector or delete the unique_ptrs.
    
    auto finalize = [&] (auto& vector) {
        for (auto& pair : vector) {
            if (!pair.second->finalize(vm))
                *pair.second = { };
        }
    };
    forEachVector(finalize);
}

void RecordedStatuses::finalize(VM& vm)
{
    auto finalize = [&] (auto& vector) {
        vector.removeAllMatching(
            [&] (auto& pair) -> bool {
                return !*pair.second || !pair.second->finalize(vm);
            });
        vector.shrinkToFit();
    };
    forEachVector(finalize);
}

void RecordedStatuses::shrinkToFit()
{
    forEachVector([] (auto& vector) { vector.shrinkToFit(); });
}

} // namespace JSC

