1// Copyright 2009 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_EXECUTION_SIMULATOR_H_
6#define V8_EXECUTION_SIMULATOR_H_
7
8#include "src/common/globals.h"
9#include "src/objects/code.h"
10
11#if !defined(USE_SIMULATOR)
12#include "src/utils/utils.h"
13#endif
14
15#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64
16// No simulator for ia32 or x64.
17#elif V8_TARGET_ARCH_ARM64
18#include "src/execution/arm64/simulator-arm64.h"
19#elif V8_TARGET_ARCH_ARM
20#include "src/execution/arm/simulator-arm.h"
21#elif V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_PPC64
22#include "src/execution/ppc/simulator-ppc.h"
23#elif V8_TARGET_ARCH_MIPS
24#include "src/execution/mips/simulator-mips.h"
25#elif V8_TARGET_ARCH_MIPS64
26#include "src/execution/mips64/simulator-mips64.h"
27#elif V8_TARGET_ARCH_LOONG64
28#include "src/execution/loong64/simulator-loong64.h"
29#elif V8_TARGET_ARCH_S390
30#include "src/execution/s390/simulator-s390.h"
31#elif V8_TARGET_ARCH_RISCV64
32#include "src/execution/riscv64/simulator-riscv64.h"
33#else
34#error Unsupported target architecture.
35#endif
36
37namespace v8 {
38namespace internal {
39
40#if defined(USE_SIMULATOR)
41// Running with a simulator.
42
43// The simulator has its own stack. Thus it has a different stack limit from
44// the C-based native code.  The JS-based limit normally points near the end of
45// the simulator stack.  When the C-based limit is exhausted we reflect that by
46// lowering the JS-based limit as well, to make stack checks trigger.
47class SimulatorStack : public v8::internal::AllStatic {
48 public:
49  static inline uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate,
50                                            uintptr_t c_limit) {
51    return Simulator::current(isolate)->StackLimit(c_limit);
52  }
53
54  // Returns the current stack address on the simulator stack frame.
55  // The returned address is comparable with JS stack address.
56  static inline uintptr_t RegisterJSStackComparableAddress(
57      v8::internal::Isolate* isolate) {
58    // The value of |kPlaceHolder| is actually not used.  It just occupies a
59    // single word on the stack frame of the simulator.
60    const uintptr_t kPlaceHolder = 0x4A535350u;  // "JSSP" in ASCII
61    return Simulator::current(isolate)->PushAddress(kPlaceHolder);
62  }
63
64  static inline void UnregisterJSStackComparableAddress(
65      v8::internal::Isolate* isolate) {
66    Simulator::current(isolate)->PopAddress();
67  }
68};
69
70#else  // defined(USE_SIMULATOR)
71// Running without a simulator on a native platform.
72
73// The stack limit beyond which we will throw stack overflow errors in
74// generated code. Because generated code uses the C stack, we just use
75// the C stack limit.
76class SimulatorStack : public v8::internal::AllStatic {
77 public:
78  static inline uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate,
79                                            uintptr_t c_limit) {
80    USE(isolate);
81    return c_limit;
82  }
83
84  // Returns the current stack address on the native stack frame.
85  // The returned address is comparable with JS stack address.
86  static inline uintptr_t RegisterJSStackComparableAddress(
87      v8::internal::Isolate* isolate) {
88    USE(isolate);
89    return internal::GetCurrentStackPosition();
90  }
91
92  static inline void UnregisterJSStackComparableAddress(
93      v8::internal::Isolate* isolate) {
94    USE(isolate);
95  }
96};
97
98#endif  // defined(USE_SIMULATOR)
99
100// Use this class either as {GeneratedCode<ret, arg1, arg2>} or
101// {GeneratedCode<ret(arg1, arg2)>} (see specialization below).
102template <typename Return, typename... Args>
103class GeneratedCode {
104 public:
105  using Signature = Return(Args...);
106
107  static GeneratedCode FromAddress(Isolate* isolate, Address addr) {
108    return GeneratedCode(isolate, reinterpret_cast<Signature*>(addr));
109  }
110
111  static GeneratedCode FromBuffer(Isolate* isolate, byte* buffer) {
112    return GeneratedCode(isolate, reinterpret_cast<Signature*>(buffer));
113  }
114
115  static GeneratedCode FromCode(Code code) {
116    return FromAddress(code.GetIsolate(), code.entry());
117  }
118
119#ifdef USE_SIMULATOR
120  // Defined in simulator-base.h.
121  Return Call(Args... args) {
122// Starboard is a platform abstraction interface that also include Windows
123// platforms like UWP.
124#if defined(V8_TARGET_OS_WIN) && !defined(V8_OS_WIN) && \
125    !defined(V8_OS_STARBOARD) && !defined(V8_TARGET_ARCH_ARM)
126    FATAL(
127        "Generated code execution not possible during cross-compilation."
128        "Also, generic C function calls are not implemented on 32-bit arm "
129        "yet.");
130#endif  // defined(V8_TARGET_OS_WIN) && !defined(V8_OS_WIN) &&
131        // !defined(V8_OS_STARBOARD) && !defined(V8_TARGET_ARCH_ARM)
132    return Simulator::current(isolate_)->template Call<Return>(
133        reinterpret_cast<Address>(fn_ptr_), args...);
134  }
135#else
136
137  DISABLE_CFI_ICALL Return Call(Args... args) {
138    // When running without a simulator we call the entry directly.
139// Starboard is a platform abstraction interface that also include Windows
140// platforms like UWP.
141#if defined(V8_TARGET_OS_WIN) && !defined(V8_OS_WIN) && \
142    !defined(V8_OS_STARBOARD)
143    FATAL("Generated code execution not possible during cross-compilation.");
144#endif  // defined(V8_TARGET_OS_WIN) && !defined(V8_OS_WIN)
145#if ABI_USES_FUNCTION_DESCRIPTORS
146    // AIX ABI requires function descriptors (FD).  Artificially create a pseudo
147    // FD to ensure correct dispatch to generated code.  The 'volatile'
148    // declaration is required to avoid the compiler from not observing the
149    // alias of the pseudo FD to the function pointer, and hence, optimizing the
150    // pseudo FD declaration/initialization away.
151    volatile Address function_desc[] = {reinterpret_cast<Address>(fn_ptr_), 0,
152                                        0};
153    Signature* fn = reinterpret_cast<Signature*>(function_desc);
154    return fn(args...);
155#else
156    return fn_ptr_(args...);
157#endif  // ABI_USES_FUNCTION_DESCRIPTORS
158  }
159#endif  // USE_SIMULATOR
160
161 private:
162  friend class GeneratedCode<Return(Args...)>;
163  Isolate* isolate_;
164  Signature* fn_ptr_;
165  GeneratedCode(Isolate* isolate, Signature* fn_ptr)
166      : isolate_(isolate), fn_ptr_(fn_ptr) {}
167};
168
169// Allow to use {GeneratedCode<ret(arg1, arg2)>} instead of
170// {GeneratedCode<ret, arg1, arg2>}.
171template <typename Return, typename... Args>
172class GeneratedCode<Return(Args...)> : public GeneratedCode<Return, Args...> {
173 public:
174  // Automatically convert from {GeneratedCode<ret, arg1, arg2>} to
175  // {GeneratedCode<ret(arg1, arg2)>}.
176  GeneratedCode(GeneratedCode<Return, Args...> other)
177      : GeneratedCode<Return, Args...>(other.isolate_, other.fn_ptr_) {}
178};
179
180}  // namespace internal
181}  // namespace v8
182
183#endif  // V8_EXECUTION_SIMULATOR_H_
184