/*
 * Copyright (C) 2013-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 "DFGToFTLForOSREntryDeferredCompilationCallback.h"

#if ENABLE(FTL_JIT)

#include "CodeBlock.h"
#include "DFGJITCode.h"
#include "FTLForOSREntryJITCode.h"
#include "JSCInlines.h"

namespace JSC { namespace DFG {

ToFTLForOSREntryDeferredCompilationCallback::ToFTLForOSREntryDeferredCompilationCallback(JITCode::TriggerReason* forcedOSREntryTrigger)
    : m_forcedOSREntryTrigger(forcedOSREntryTrigger)
{
}

ToFTLForOSREntryDeferredCompilationCallback::~ToFTLForOSREntryDeferredCompilationCallback()
{
}

Ref<ToFTLForOSREntryDeferredCompilationCallback>ToFTLForOSREntryDeferredCompilationCallback::create(JITCode::TriggerReason* forcedOSREntryTrigger)
{
    return adoptRef(*new ToFTLForOSREntryDeferredCompilationCallback(forcedOSREntryTrigger));
}

void ToFTLForOSREntryDeferredCompilationCallback::compilationDidBecomeReadyAsynchronously(
    CodeBlock* codeBlock, CodeBlock* profiledDFGCodeBlock)
{
    dataLogLnIf(Options::verboseOSR(),
        "Optimizing compilation of ", *codeBlock, " (for ", *profiledDFGCodeBlock,
        ") did become ready.");

    *m_forcedOSREntryTrigger = JITCode::TriggerReason::CompilationDone;
}

void ToFTLForOSREntryDeferredCompilationCallback::compilationDidComplete(
    CodeBlock* codeBlock, CodeBlock* profiledDFGCodeBlock, CompilationResult result)
{
    dataLogLnIf(Options::verboseOSR(),
        "Optimizing compilation of ", *codeBlock, " (for ", *profiledDFGCodeBlock,
        ") result: ", result);
    
    JITCode* jitCode = profiledDFGCodeBlock->jitCode()->dfg();
        
    switch (result) {
    case CompilationSuccessful: {
        jitCode->setOSREntryBlock(codeBlock->vm(), profiledDFGCodeBlock, codeBlock);
        BytecodeIndex osrEntryBytecode = codeBlock->jitCode()->ftlForOSREntry()->bytecodeIndex();
        jitCode->tierUpEntryTriggers.set(osrEntryBytecode, JITCode::TriggerReason::CompilationDone);
        break;
    }
    case CompilationFailed:
        jitCode->osrEntryRetry = 0;
        jitCode->abandonOSREntry = true;
        profiledDFGCodeBlock->jitCode()->dfg()->setOptimizationThresholdBasedOnCompilationResult(
            profiledDFGCodeBlock, result);
        break;
    case CompilationDeferred:
        RELEASE_ASSERT_NOT_REACHED();
    case CompilationInvalidated:
        jitCode->osrEntryRetry = 0;
        break;
    }
    
    DeferredCompilationCallback::compilationDidComplete(codeBlock, profiledDFGCodeBlock, result);
}

} } // JSC::DFG

#endif // ENABLE(FTL_JIT)
