/*
 * Copyright (C) 2017 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.
 */

#pragma once

#if ENABLE(WEBASSEMBLY)

#include "CompilationResult.h"
#include "ExecutionCounter.h"
#include "Options.h"
#include <wtf/Atomics.h>
#include <wtf/SegmentedVector.h>
#include <wtf/StdLibExtras.h>

namespace JSC { namespace Wasm {

class OSREntryData;

// This class manages the tier up counts for Wasm binaries. The main interesting thing about
// wasm tiering up counts is that the least significant bit indicates if the tier up has already
// started. Also, wasm code does not atomically update this count. This is because we
// don't care too much if the countdown is slightly off. The tier up trigger is atomic, however,
// so tier up will be triggered exactly once.
class TierUpCount : public UpperTierExecutionCounter {
    WTF_MAKE_NONCOPYABLE(TierUpCount);
public:
    enum class TriggerReason : uint8_t {
        DontTrigger,
        CompilationDone,
        StartCompilation,
    };

    enum class CompilationStatus : uint8_t {
        NotCompiled,
        StartCompilation,
        Compiled,
        Failed,
    };

    TierUpCount();
    ~TierUpCount();

    static int32_t loopIncrement() { return Options::omgTierUpCounterIncrementForLoop(); }
    static int32_t functionEntryIncrement() { return Options::omgTierUpCounterIncrementForEntry(); }

    SegmentedVector<TriggerReason, 16>& osrEntryTriggers() { return m_osrEntryTriggers; }
    Vector<uint32_t>& outerLoops() { return m_outerLoops; }
    Lock& getLock() { return m_lock; }

    OSREntryData& addOSREntryData(uint32_t functionIndex, uint32_t loopIndex);

    void optimizeAfterWarmUp(uint32_t functionIndex)
    {
        dataLogLnIf(Options::verboseOSR(), functionIndex, ": OMG-optimizing after warm-up.");
        setNewThreshold(Options::thresholdForOMGOptimizeAfterWarmUp(), nullptr);
    }

    bool checkIfOptimizationThresholdReached()
    {
        return checkIfThresholdCrossedAndSet(nullptr);
    }

    void dontOptimizeAnytimeSoon(uint32_t functionIndex)
    {
        dataLogLnIf(Options::verboseOSR(), functionIndex, ": Not OMG-optimizing anytime soon.");
        deferIndefinitely();
    }

    void optimizeNextInvocation(uint32_t functionIndex)
    {
        dataLogLnIf(Options::verboseOSR(), functionIndex, ": OMG-optimizing next invocation.");
        setNewThreshold(0, nullptr);
    }

    void optimizeSoon(uint32_t functionIndex)
    {
        dataLogLnIf(Options::verboseOSR(), functionIndex, ": OMG-optimizing soon.");
        // FIXME: Need adjustment once we get more information about wasm functions.
        setNewThreshold(Options::thresholdForOMGOptimizeSoon(), nullptr);
    }

    void setOptimizationThresholdBasedOnCompilationResult(uint32_t functionIndex, CompilationResult result)
    {
        switch (result) {
        case CompilationSuccessful:
            optimizeNextInvocation(functionIndex);
            return;
        case CompilationFailed:
            dontOptimizeAnytimeSoon(functionIndex);
            return;
        case CompilationDeferred:
            optimizeAfterWarmUp(functionIndex);
            return;
        case CompilationInvalidated:
            // This is weird - it will only happen in cases when the DFG code block (i.e.
            // the code block that this JITCode belongs to) is also invalidated. So it
            // doesn't really matter what we do. But, we do the right thing anyway. Note
            // that us counting the reoptimization actually means that we might count it
            // twice. But that's generally OK. It's better to overcount reoptimizations
            // than it is to undercount them.
            optimizeAfterWarmUp(functionIndex);
            return;
        }
        RELEASE_ASSERT_NOT_REACHED();
    }

    Atomic<bool> m_tierUpStarted { false };
    Lock m_lock;
    CompilationStatus m_compilationStatusForOMG { CompilationStatus::NotCompiled };
    CompilationStatus m_compilationStatusForOMGForOSREntry { CompilationStatus::NotCompiled };
    SegmentedVector<TriggerReason, 16> m_osrEntryTriggers;
    Vector<uint32_t> m_outerLoops;
    Vector<std::unique_ptr<OSREntryData>> m_osrEntryData;
};
    
} } // namespace JSC::Wasm

#endif // ENABLE(WEBASSEMBLY)
