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

#if ENABLE(FTL_JIT)

#include "B3StackmapGenerationParams.h"
#include "FTLExceptionTarget.h"
#include "FTLOSRExit.h"
#include "FTLOSRExitHandle.h"
#include "FTLState.h"

namespace JSC { namespace FTL {

using namespace DFG;

Ref<PatchpointExceptionHandle> PatchpointExceptionHandle::create(
    State& state, OSRExitDescriptor* descriptor, NodeOrigin origin, unsigned dfgNodeIndex, unsigned offset,
    const HandlerInfo& handler)
{
    return adoptRef(*new PatchpointExceptionHandle(state, descriptor, origin, dfgNodeIndex, offset, handler));
}

RefPtr<PatchpointExceptionHandle> PatchpointExceptionHandle::defaultHandle(State& state, unsigned dfgNodeIndex)
{
    if (!state.defaultExceptionHandle) {
        state.defaultExceptionHandle = adoptRef(
            new PatchpointExceptionHandle(state, nullptr, NodeOrigin(), dfgNodeIndex, 0, HandlerInfo()));
    }
    return state.defaultExceptionHandle;
}

PatchpointExceptionHandle::~PatchpointExceptionHandle()
{
}

RefPtr<ExceptionTarget> PatchpointExceptionHandle::scheduleExitCreation(
    const B3::StackmapGenerationParams& params)
{
    if (!m_descriptor) {
        // NOTE: This object could be a singleton, however usually we toss the ExceptionHandler
        // object shortly after creation.
        bool isDefaultHandler = true;
        return adoptRef(
            new ExceptionTarget(isDefaultHandler, m_state.exceptionHandler, nullptr));
    }
    bool isDefaultHandler = false;
    return adoptRef(new ExceptionTarget(isDefaultHandler, { }, createHandle(ExceptionCheck, params)));
}

void PatchpointExceptionHandle::scheduleExitCreationForUnwind(
    const B3::StackmapGenerationParams& params, CallSiteIndex callSiteIndex)
{
    if (!m_descriptor)
        return;
    
    RefPtr<OSRExitHandle> handle = createHandle(GenericUnwind, params);

    handle->exit.m_exceptionHandlerCallSiteIndex = callSiteIndex;

    HandlerInfo handler = m_handler;
    params.addLatePath(
        [handle, handler, callSiteIndex] (CCallHelpers& jit) {
            CodeBlock* codeBlock = jit.codeBlock();
            jit.addLinkTask(
                [=] (LinkBuffer& linkBuffer) {
                    HandlerInfo newHandler = handler;
                    newHandler.start = callSiteIndex.bits();
                    newHandler.end = callSiteIndex.bits() + 1;
                    newHandler.nativeCode = linkBuffer.locationOf<ExceptionHandlerPtrTag>(handle->label);
                    codeBlock->appendExceptionHandler(newHandler);
                });
        });
}

PatchpointExceptionHandle::PatchpointExceptionHandle(
    State& state, OSRExitDescriptor* descriptor, NodeOrigin origin, unsigned dfgNodeIndex, unsigned offset,
    const HandlerInfo& handler)
    : m_state(state)
    , m_descriptor(descriptor)
    , m_origin(origin)
    , m_dfgNodeIndex(dfgNodeIndex)
    , m_offset(offset)
    , m_handler(handler)
{
}

Ref<OSRExitHandle> PatchpointExceptionHandle::createHandle(
    ExitKind kind, const B3::StackmapGenerationParams& params)
{
    return m_descriptor->emitOSRExitLater(
        m_state, kind, m_origin, params, m_dfgNodeIndex, m_offset);
}

} } // namespace JSC::FTL

#endif // ENABLE(FTL_JIT)

