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