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_SIMULATOR_H_ 6 #define V8_SIMULATOR_H_ 7 8 #include "src/globals.h" 9 #include "src/objects/code.h" 10 11 #if V8_TARGET_ARCH_IA32 12 #include "src/ia32/simulator-ia32.h" 13 #elif V8_TARGET_ARCH_X64 14 #include "src/x64/simulator-x64.h" 15 #elif V8_TARGET_ARCH_ARM64 16 #include "src/arm64/simulator-arm64.h" 17 #elif V8_TARGET_ARCH_ARM 18 #include "src/arm/simulator-arm.h" 19 #elif V8_TARGET_ARCH_PPC 20 #include "src/ppc/simulator-ppc.h" 21 #elif V8_TARGET_ARCH_MIPS 22 #include "src/mips/simulator-mips.h" 23 #elif V8_TARGET_ARCH_MIPS64 24 #include "src/mips64/simulator-mips64.h" 25 #elif V8_TARGET_ARCH_S390 26 #include "src/s390/simulator-s390.h" 27 #else 28 #error Unsupported target architecture. 29 #endif 30 31 namespace v8 { 32 namespace internal { 33 34 #if defined(USE_SIMULATOR) 35 // Running with a simulator. 36 37 // The simulator has its own stack. Thus it has a different stack limit from 38 // the C-based native code. The JS-based limit normally points near the end of 39 // the simulator stack. When the C-based limit is exhausted we reflect that by 40 // lowering the JS-based limit as well, to make stack checks trigger. 41 class SimulatorStack : public v8::internal::AllStatic { 42 public: JsLimitFromCLimit(v8::internal::Isolate * isolate,uintptr_t c_limit)43 static inline uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate, 44 uintptr_t c_limit) { 45 return Simulator::current(isolate)->StackLimit(c_limit); 46 } 47 RegisterCTryCatch(v8::internal::Isolate * isolate,uintptr_t try_catch_address)48 static inline uintptr_t RegisterCTryCatch(v8::internal::Isolate* isolate, 49 uintptr_t try_catch_address) { 50 return Simulator::current(isolate)->PushAddress(try_catch_address); 51 } 52 UnregisterCTryCatch(v8::internal::Isolate * isolate)53 static inline void UnregisterCTryCatch(v8::internal::Isolate* isolate) { 54 Simulator::current(isolate)->PopAddress(); 55 } 56 }; 57 58 #else // defined(USE_SIMULATOR) 59 // Running without a simulator on a native platform. 60 61 // The stack limit beyond which we will throw stack overflow errors in 62 // generated code. Because generated code uses the C stack, we just use 63 // the C stack limit. 64 class SimulatorStack : public v8::internal::AllStatic { 65 public: 66 static inline uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate, 67 uintptr_t c_limit) { 68 USE(isolate); 69 return c_limit; 70 } 71 72 static inline uintptr_t RegisterCTryCatch(v8::internal::Isolate* isolate, 73 uintptr_t try_catch_address) { 74 USE(isolate); 75 return try_catch_address; 76 } 77 78 static inline void UnregisterCTryCatch(v8::internal::Isolate* isolate) { 79 USE(isolate); 80 } 81 }; 82 83 #endif // defined(USE_SIMULATOR) 84 85 // Use this class either as {GeneratedCode<ret, arg1, arg2>} or 86 // {GeneratedCode<ret(arg1, arg2)>} (see specialization below). 87 template <typename Return, typename... Args> 88 class GeneratedCode { 89 public: 90 using Signature = Return(Args...); 91 FromAddress(Isolate * isolate,Address addr)92 static GeneratedCode FromAddress(Isolate* isolate, Address addr) { 93 return GeneratedCode(isolate, reinterpret_cast<Signature*>(addr)); 94 } 95 FromBuffer(Isolate * isolate,byte * buffer)96 static GeneratedCode FromBuffer(Isolate* isolate, byte* buffer) { 97 return GeneratedCode(isolate, reinterpret_cast<Signature*>(buffer)); 98 } 99 FromCode(Code * code)100 static GeneratedCode FromCode(Code* code) { 101 return FromAddress(code->GetIsolate(), code->entry()); 102 } 103 104 #ifdef USE_SIMULATOR 105 // Defined in simulator-base.h. Call(Args...args)106 Return Call(Args... args) { 107 return Simulator::current(isolate_)->template Call<Return>( 108 reinterpret_cast<Address>(fn_ptr_), args...); 109 } 110 #else Call(Args...args)111 DISABLE_CFI_ICALL Return Call(Args... args) { 112 // When running without a simulator we call the entry directly. 113 return fn_ptr_(args...); 114 } 115 #endif 116 117 private: 118 friend class GeneratedCode<Return(Args...)>; 119 Isolate* isolate_; 120 Signature* fn_ptr_; GeneratedCode(Isolate * isolate,Signature * fn_ptr)121 GeneratedCode(Isolate* isolate, Signature* fn_ptr) 122 : isolate_(isolate), fn_ptr_(fn_ptr) {} 123 }; 124 125 // Allow to use {GeneratedCode<ret(arg1, arg2)>} instead of 126 // {GeneratedCode<ret, arg1, arg2>}. 127 template <typename Return, typename... Args> 128 class GeneratedCode<Return(Args...)> : public GeneratedCode<Return, Args...> { 129 public: 130 // Automatically convert from {GeneratedCode<ret, arg1, arg2>} to 131 // {GeneratedCode<ret(arg1, arg2)>}. GeneratedCode(GeneratedCode<Return,Args...> other)132 GeneratedCode(GeneratedCode<Return, Args...> other) 133 : GeneratedCode<Return, Args...>(other.isolate_, other.fn_ptr_) {} 134 }; 135 136 } // namespace internal 137 } // namespace v8 138 139 #endif // V8_SIMULATOR_H_ 140