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