Home | History | Annotate | Download | only in src
      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:
     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 
     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 
     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 
     92   static GeneratedCode FromAddress(Isolate* isolate, Address addr) {
     93     return GeneratedCode(isolate, reinterpret_cast<Signature*>(addr));
     94   }
     95 
     96   static GeneratedCode FromBuffer(Isolate* isolate, byte* buffer) {
     97     return GeneratedCode(isolate, reinterpret_cast<Signature*>(buffer));
     98   }
     99 
    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.
    106   Return Call(Args... args) {
    107     return Simulator::current(isolate_)->template Call<Return>(
    108         reinterpret_cast<Address>(fn_ptr_), args...);
    109   }
    110 #else
    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_;
    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)>}.
    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