• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
37 namespace v8 {
38 namespace 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.
47 class SimulatorStack : public v8::internal::AllStatic {
48  public:
JsLimitFromCLimit(v8::internal::Isolate * isolate,uintptr_t c_limit)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.
RegisterJSStackComparableAddress(v8::internal::Isolate * isolate)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 
UnregisterJSStackComparableAddress(v8::internal::Isolate * isolate)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.
76 class 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).
102 template <typename Return, typename... Args>
103 class GeneratedCode {
104  public:
105   using Signature = Return(Args...);
106 
FromAddress(Isolate * isolate,Address addr)107   static GeneratedCode FromAddress(Isolate* isolate, Address addr) {
108     return GeneratedCode(isolate, reinterpret_cast<Signature*>(addr));
109   }
110 
FromBuffer(Isolate * isolate,byte * buffer)111   static GeneratedCode FromBuffer(Isolate* isolate, byte* buffer) {
112     return GeneratedCode(isolate, reinterpret_cast<Signature*>(buffer));
113   }
114 
FromCode(Code code)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.
Call(Args...args)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 
Call(Args...args)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_;
GeneratedCode(Isolate * isolate,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>}.
171 template <typename Return, typename... Args>
172 class GeneratedCode<Return(Args...)> : public GeneratedCode<Return, Args...> {
173  public:
174   // Automatically convert from {GeneratedCode<ret, arg1, arg2>} to
175   // {GeneratedCode<ret(arg1, arg2)>}.
GeneratedCode(GeneratedCode<Return,Args...> other)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