blob: 74763474c6174d09ac18f50e9d6a1493e0288e1f [file] [log] [blame]
Rubin Xu7bc1b612021-02-16 09:38:50 +00001// 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_S390
28#include "src/execution/s390/simulator-s390.h"
29#else
30#error Unsupported target architecture.
31#endif
32
33namespace v8 {
34namespace internal {
35
36#if defined(USE_SIMULATOR)
37// Running with a simulator.
38
39// The simulator has its own stack. Thus it has a different stack limit from
40// the C-based native code. The JS-based limit normally points near the end of
41// the simulator stack. When the C-based limit is exhausted we reflect that by
42// lowering the JS-based limit as well, to make stack checks trigger.
43class SimulatorStack : public v8::internal::AllStatic {
44 public:
45 static inline uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate,
46 uintptr_t c_limit) {
47 return Simulator::current(isolate)->StackLimit(c_limit);
48 }
49
50 // Returns the current stack address on the simulator stack frame.
51 // The returned address is comparable with JS stack address.
52 static inline uintptr_t RegisterJSStackComparableAddress(
53 v8::internal::Isolate* isolate) {
54 // The value of |kPlaceHolder| is actually not used. It just occupies a
55 // single word on the stack frame of the simulator.
56 const uintptr_t kPlaceHolder = 0x4A535350u; // "JSSP" in ASCII
57 return Simulator::current(isolate)->PushAddress(kPlaceHolder);
58 }
59
60 static inline void UnregisterJSStackComparableAddress(
61 v8::internal::Isolate* isolate) {
62 Simulator::current(isolate)->PopAddress();
63 }
64};
65
66#else // defined(USE_SIMULATOR)
67// Running without a simulator on a native platform.
68
69// The stack limit beyond which we will throw stack overflow errors in
70// generated code. Because generated code uses the C stack, we just use
71// the C stack limit.
72class SimulatorStack : public v8::internal::AllStatic {
73 public:
74 static inline uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate,
75 uintptr_t c_limit) {
76 USE(isolate);
77 return c_limit;
78 }
79
80 // Returns the current stack address on the native stack frame.
81 // The returned address is comparable with JS stack address.
82 static inline uintptr_t RegisterJSStackComparableAddress(
83 v8::internal::Isolate* isolate) {
84 USE(isolate);
85 return internal::GetCurrentStackPosition();
86 }
87
88 static inline void UnregisterJSStackComparableAddress(
89 v8::internal::Isolate* isolate) {
90 USE(isolate);
91 }
92};
93
94#endif // defined(USE_SIMULATOR)
95
96// Use this class either as {GeneratedCode<ret, arg1, arg2>} or
97// {GeneratedCode<ret(arg1, arg2)>} (see specialization below).
98template <typename Return, typename... Args>
99class GeneratedCode {
100 public:
101 using Signature = Return(Args...);
102
103 static GeneratedCode FromAddress(Isolate* isolate, Address addr) {
104 return GeneratedCode(isolate, reinterpret_cast<Signature*>(addr));
105 }
106
107 static GeneratedCode FromBuffer(Isolate* isolate, byte* buffer) {
108 return GeneratedCode(isolate, reinterpret_cast<Signature*>(buffer));
109 }
110
111 static GeneratedCode FromCode(Code code) {
112 return FromAddress(code.GetIsolate(), code.entry());
113 }
114
115#ifdef USE_SIMULATOR
116 // Defined in simulator-base.h.
117 Return Call(Args... args) {
118#if defined(V8_TARGET_OS_WIN) && !defined(V8_OS_WIN)
119 FATAL("Generated code execution not possible during cross-compilation.");
120#endif // defined(V8_TARGET_OS_WIN) && !defined(V8_OS_WIN)
121 return Simulator::current(isolate_)->template Call<Return>(
122 reinterpret_cast<Address>(fn_ptr_), args...);
123 }
124#else
125
126 DISABLE_CFI_ICALL Return Call(Args... args) {
127 // When running without a simulator we call the entry directly.
128#if defined(V8_TARGET_OS_WIN) && !defined(V8_OS_WIN)
129 FATAL("Generated code execution not possible during cross-compilation.");
130#endif // defined(V8_TARGET_OS_WIN) && !defined(V8_OS_WIN)
131#if ABI_USES_FUNCTION_DESCRIPTORS
132 // AIX ABI requires function descriptors (FD). Artificially create a pseudo
133 // FD to ensure correct dispatch to generated code. The 'volatile'
134 // declaration is required to avoid the compiler from not observing the
135 // alias of the pseudo FD to the function pointer, and hence, optimizing the
136 // pseudo FD declaration/initialization away.
137 volatile Address function_desc[] = {reinterpret_cast<Address>(fn_ptr_), 0,
138 0};
139 Signature* fn = reinterpret_cast<Signature*>(function_desc);
140 return fn(args...);
141#else
142 return fn_ptr_(args...);
143#endif // ABI_USES_FUNCTION_DESCRIPTORS
144 }
145#endif // USE_SIMULATOR
146
147 private:
148 friend class GeneratedCode<Return(Args...)>;
149 Isolate* isolate_;
150 Signature* fn_ptr_;
151 GeneratedCode(Isolate* isolate, Signature* fn_ptr)
152 : isolate_(isolate), fn_ptr_(fn_ptr) {}
153};
154
155// Allow to use {GeneratedCode<ret(arg1, arg2)>} instead of
156// {GeneratedCode<ret, arg1, arg2>}.
157template <typename Return, typename... Args>
158class GeneratedCode<Return(Args...)> : public GeneratedCode<Return, Args...> {
159 public:
160 // Automatically convert from {GeneratedCode<ret, arg1, arg2>} to
161 // {GeneratedCode<ret(arg1, arg2)>}.
162 GeneratedCode(GeneratedCode<Return, Args...> other)
163 : GeneratedCode<Return, Args...>(other.isolate_, other.fn_ptr_) {}
164};
165
166} // namespace internal
167} // namespace v8
168
169#endif // V8_EXECUTION_SIMULATOR_H_