/*
 * 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.
 */

#include "config.h"
#include "ProbeContext.h"

#if ENABLE(MASM_PROBE)

namespace JSC {
namespace Probe {

static void flushDirtyStackPages(State*);

void executeProbe(State* state)
{
    Context context(state);
#if CPU(ARM64)
    auto& cpu = context.cpu;
    void* originalLR = cpu.gpr<void*>(ARM64Registers::lr);
    void* originalPC = cpu.pc();
#elif CPU(MIPS)
    auto& cpu = context.cpu;
    void* originalRA = cpu.gpr<void*>(MIPSRegisters::ra);
    void* originalPC = cpu.pc();
#endif

    state->initializeStackFunction = nullptr;
    state->initializeStackArg = nullptr;
    state->probeFunction(context);

#if CPU(ARM64)
    // The ARM64 probe trampoline does not support changing both lr and pc.
    RELEASE_ASSERT(originalPC == cpu.pc() || originalLR == cpu.gpr<void*>(ARM64Registers::lr));
#elif CPU(MIPS)
    // The MIPS probe trampoline does not support changing both ra and pc.
    RELEASE_ASSERT(originalPC == cpu.pc() || originalRA == cpu.gpr<void*>(MIPSRegisters::ra));
#endif

    if (context.hasWritesToFlush()) {
        context.stack().setSavedStackPointer(state->cpu.sp());
        void* lowWatermark = context.stack().lowWatermarkFromVisitingDirtyPages();
        state->cpu.sp() = std::min(lowWatermark, state->cpu.sp());

        state->initializeStackFunction = flushDirtyStackPages;
        state->initializeStackArg = context.releaseStack();
    }
}

static void flushDirtyStackPages(State* state)
{
    std::unique_ptr<Stack> stack(reinterpret_cast<Probe::Stack*>(state->initializeStackArg));
    stack->flushWrites();
    state->cpu.sp() = stack->savedStackPointer();
}

// Not for general use. This should only be for writing tests.
JS_EXPORT_PRIVATE void* probeStateForContext(Context&);
void* probeStateForContext(Context& context)
{
    return context.m_state;
}

} // namespace Probe
} // namespace JSC

#endif // ENABLE(MASM_PROBE)
