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_S390 28 #include "src/execution/s390/simulator-s390.h" 29 #else 30 #error Unsupported target architecture. 31 #endif 32 33 namespace v8 { 34 namespace 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. 43 class SimulatorStack : public v8::internal::AllStatic { 44 public: JsLimitFromCLimit(v8::internal::Isolate * isolate,uintptr_t c_limit)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. RegisterJSStackComparableAddress(v8::internal::Isolate * isolate)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 UnregisterJSStackComparableAddress(v8::internal::Isolate * isolate)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. 72 class 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). 98 template <typename Return, typename... Args> 99 class GeneratedCode { 100 public: 101 using Signature = Return(Args...); 102 FromAddress(Isolate * isolate,Address addr)103 static GeneratedCode FromAddress(Isolate* isolate, Address addr) { 104 return GeneratedCode(isolate, reinterpret_cast<Signature*>(addr)); 105 } 106 FromBuffer(Isolate * isolate,byte * buffer)107 static GeneratedCode FromBuffer(Isolate* isolate, byte* buffer) { 108 return GeneratedCode(isolate, reinterpret_cast<Signature*>(buffer)); 109 } 110 FromCode(Code code)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. Call(Args...args)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 Call(Args...args)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_; GeneratedCode(Isolate * isolate,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>}. 157 template <typename Return, typename... Args> 158 class GeneratedCode<Return(Args...)> : public GeneratedCode<Return, Args...> { 159 public: 160 // Automatically convert from {GeneratedCode<ret, arg1, arg2>} to 161 // {GeneratedCode<ret(arg1, arg2)>}. GeneratedCode(GeneratedCode<Return,Args...> other)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_ 170