chromium/v8/src/execution/simulator.h

// Copyright 2009 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_EXECUTION_SIMULATOR_H_
#define V8_EXECUTION_SIMULATOR_H_

#include "src/common/globals.h"
#include "src/objects/code.h"

#if !defined(USE_SIMULATOR)
#include "src/base/platform/platform.h"
#include "src/execution/isolate.h"
#include "src/utils/utils.h"
#endif

#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64
// No simulator for ia32 or x64.
#elif V8_TARGET_ARCH_ARM64
#include "src/execution/arm64/simulator-arm64.h"
#elif V8_TARGET_ARCH_ARM
#include "src/execution/arm/simulator-arm.h"
#elif V8_TARGET_ARCH_PPC64
#include "src/execution/ppc/simulator-ppc.h"
#elif V8_TARGET_ARCH_MIPS64
#include "src/execution/mips64/simulator-mips64.h"
#elif V8_TARGET_ARCH_LOONG64
#include "src/execution/loong64/simulator-loong64.h"
#elif V8_TARGET_ARCH_S390
#include "src/execution/s390/simulator-s390.h"
#elif V8_TARGET_ARCH_RISCV32 || V8_TARGET_ARCH_RISCV64
#include "src/execution/riscv/simulator-riscv.h"
#else
#error Unsupported target architecture.
#endif

namespace v8 {
namespace internal {

#if defined(USE_SIMULATOR)
// Running with a simulator.

// The simulator has its own stack. Thus it has a different stack limit from
// the C-based native code.  The JS-based limit normally points near the end of
// the simulator stack.  When the C-based limit is exhausted we reflect that by
// lowering the JS-based limit as well, to make stack checks trigger.
class SimulatorStack : public v8::internal::AllStatic {
 public:
  static inline uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate,
                                            uintptr_t c_limit) {
    return Simulator::current(isolate)->StackLimit(c_limit);
  }

  static inline base::Vector<uint8_t> GetCurrentStackView(
      v8::internal::Isolate* isolate) {
    return Simulator::current(isolate)->GetCurrentStackView();
  }

  // When running on the simulator, we should leave the C stack limits alone
  // when switching stacks for Wasm.
  static inline bool ShouldSwitchCStackForWasmStackSwitching() { return false; }

  // Returns the current stack address on the simulator stack frame.
  // The returned address is comparable with JS stack address.
  static inline uintptr_t RegisterJSStackComparableAddress(
      v8::internal::Isolate* isolate) {
    // The value of |kPlaceHolder| is actually not used.  It just occupies a
    // single word on the stack frame of the simulator.
    const uintptr_t kPlaceHolder = 0x4A535350u;  // "JSSP" in ASCII
    return Simulator::current(isolate)->PushAddress(kPlaceHolder);
  }

  static inline void UnregisterJSStackComparableAddress(
      v8::internal::Isolate* isolate) {
    Simulator::current(isolate)->PopAddress();
  }
};

#else  // defined(USE_SIMULATOR)
// Running without a simulator on a native platform.

// The stack limit beyond which we will throw stack overflow errors in
// generated code. Because generated code uses the C stack, we just use
// the C stack limit.
class SimulatorStack : public v8::internal::AllStatic {};

#endif  // defined(USE_SIMULATOR)

// Use this class either as {GeneratedCode<ret, arg1, arg2>} or
// {GeneratedCode<ret(arg1, arg2)>} (see specialization below).
template <typename Return, typename... Args>
class GeneratedCode {};

// Allow to use {GeneratedCode<ret(arg1, arg2)>} instead of
// {GeneratedCode<ret, arg1, arg2>}.
GeneratedCode<Return (Args...)>;

}  // namespace internal
}  // namespace v8

#endif  // V8_EXECUTION_SIMULATOR_H_