• 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_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