/*
 * 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().lowWatermark(state->cpu.sp());
        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)
