ProbeContext.cpp
1 /* 2 * Copyright (C) 2017 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "config.h" 27 #include "ProbeContext.h" 28 29 #if ENABLE(MASM_PROBE) 30 31 namespace JSC { 32 namespace Probe { 33 34 static void flushDirtyStackPages(State*); 35 36 void executeProbe(State* state) 37 { 38 Context context(state); 39 #if CPU(ARM64) 40 auto& cpu = context.cpu; 41 void* originalLR = cpu.gpr<void*>(ARM64Registers::lr); 42 void* originalPC = cpu.pc(); 43 #elif CPU(MIPS) 44 auto& cpu = context.cpu; 45 void* originalRA = cpu.gpr<void*>(MIPSRegisters::ra); 46 void* originalPC = cpu.pc(); 47 #endif 48 49 state->initializeStackFunction = nullptr; 50 state->initializeStackArg = nullptr; 51 state->probeFunction(context); 52 53 #if CPU(ARM64) 54 // The ARM64 probe trampoline does not support changing both lr and pc. 55 RELEASE_ASSERT(originalPC == cpu.pc() || originalLR == cpu.gpr<void*>(ARM64Registers::lr)); 56 #elif CPU(MIPS) 57 // The MIPS probe trampoline does not support changing both ra and pc. 58 RELEASE_ASSERT(originalPC == cpu.pc() || originalRA == cpu.gpr<void*>(MIPSRegisters::ra)); 59 #endif 60 61 if (context.hasWritesToFlush()) { 62 context.stack().setSavedStackPointer(state->cpu.sp()); 63 void* lowWatermark = context.stack().lowWatermarkFromVisitingDirtyPages(); 64 state->cpu.sp() = std::min(lowWatermark, state->cpu.sp()); 65 66 state->initializeStackFunction = flushDirtyStackPages; 67 state->initializeStackArg = context.releaseStack(); 68 } 69 } 70 71 static void flushDirtyStackPages(State* state) 72 { 73 std::unique_ptr<Stack> stack(reinterpret_cast<Probe::Stack*>(state->initializeStackArg)); 74 stack->flushWrites(); 75 state->cpu.sp() = stack->savedStackPointer(); 76 } 77 78 // Not for general use. This should only be for writing tests. 79 JS_EXPORT_PRIVATE void* probeStateForContext(Context&); 80 void* probeStateForContext(Context& context) 81 { 82 return context.m_state; 83 } 84 85 } // namespace Probe 86 } // namespace JSC 87 88 #endif // ENABLE(MASM_PROBE)