/ assembler / ProbeContext.cpp
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)