simulator.h 5.37 KB
Newer Older
1
// Copyright 2009 the V8 project authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
4 5 6 7

#ifndef V8_SIMULATOR_H_
#define V8_SIMULATOR_H_

8
#include "src/globals.h"
9
#include "src/objects/code.h"
10

11 12 13 14
#if !defined(USE_SIMULATOR)
#include "src/utils.h"
#endif

15 16
#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64
// No simulator for ia32 or x64.
17
#elif V8_TARGET_ARCH_ARM64
18
#include "src/arm64/simulator-arm64.h"
19
#elif V8_TARGET_ARCH_ARM
20
#include "src/arm/simulator-arm.h"
21 22
#elif V8_TARGET_ARCH_PPC
#include "src/ppc/simulator-ppc.h"
23
#elif V8_TARGET_ARCH_MIPS
24
#include "src/mips/simulator-mips.h"
25 26
#elif V8_TARGET_ARCH_MIPS64
#include "src/mips64/simulator-mips64.h"
27 28
#elif V8_TARGET_ARCH_S390
#include "src/s390/simulator-s390.h"
29 30 31 32
#else
#error Unsupported target architecture.
#endif

33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
namespace v8 {
namespace internal {

#if defined(USE_SIMULATOR)
// Running with a simulator.

// The simulator has its own stack. Thus it has a different stack limit from
// the C-based native code.  The JS-based limit normally points near the end of
// the simulator stack.  When the C-based limit is exhausted we reflect that by
// lowering the JS-based limit as well, to make stack checks trigger.
class SimulatorStack : public v8::internal::AllStatic {
 public:
  static inline uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate,
                                            uintptr_t c_limit) {
    return Simulator::current(isolate)->StackLimit(c_limit);
  }

50 51 52 53 54 55 56 57
  // Returns the current stack address on the simulator stack frame.
  // The returned address is comparable with JS stack address.
  static inline uintptr_t RegisterJSStackComparableAddress(
      v8::internal::Isolate* isolate) {
    // The value of |kPlaceHolder| is actually not used.  It just occupies a
    // single word on the stack frame of the simulator.
    const uintptr_t kPlaceHolder = 0x4A535350u;  // "JSSP" in ASCII
    return Simulator::current(isolate)->PushAddress(kPlaceHolder);
58 59
  }

60 61
  static inline void UnregisterJSStackComparableAddress(
      v8::internal::Isolate* isolate) {
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
    Simulator::current(isolate)->PopAddress();
  }
};

#else  // defined(USE_SIMULATOR)
// Running without a simulator on a native platform.

// The stack limit beyond which we will throw stack overflow errors in
// generated code. Because generated code uses the C stack, we just use
// the C stack limit.
class SimulatorStack : public v8::internal::AllStatic {
 public:
  static inline uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate,
                                            uintptr_t c_limit) {
    USE(isolate);
    return c_limit;
  }

80 81 82 83
  // Returns the current stack address on the native stack frame.
  // The returned address is comparable with JS stack address.
  static inline uintptr_t RegisterJSStackComparableAddress(
      v8::internal::Isolate* isolate) {
84
    USE(isolate);
85
    return internal::GetCurrentStackPosition();
86 87
  }

88 89
  static inline void UnregisterJSStackComparableAddress(
      v8::internal::Isolate* isolate) {
90 91 92 93
    USE(isolate);
  }
};

94
#endif  // defined(USE_SIMULATOR)
95

96 97 98 99 100 101
// Use this class either as {GeneratedCode<ret, arg1, arg2>} or
// {GeneratedCode<ret(arg1, arg2)>} (see specialization below).
template <typename Return, typename... Args>
class GeneratedCode {
 public:
  using Signature = Return(Args...);
102

103
  static GeneratedCode FromAddress(Isolate* isolate, Address addr) {
104 105
    return GeneratedCode(isolate, reinterpret_cast<Signature*>(addr));
  }
106

107 108 109 110
  static GeneratedCode FromBuffer(Isolate* isolate, byte* buffer) {
    return GeneratedCode(isolate, reinterpret_cast<Signature*>(buffer));
  }

111
  static GeneratedCode FromCode(Code code) {
112 113 114 115 116 117 118
    return FromAddress(code->GetIsolate(), code->entry());
  }

#ifdef USE_SIMULATOR
  // Defined in simulator-base.h.
  Return Call(Args... args) {
    return Simulator::current(isolate_)->template Call<Return>(
119
        reinterpret_cast<Address>(fn_ptr_), args...);
120 121
  }
#else
122
  DISABLE_CFI_ICALL Return Call(Args... args) {
123
    // When running without a simulator we call the entry directly.
124 125 126 127 128 129 130 131 132 133 134
#if V8_OS_AIX
    // AIX ABI requires function descriptors (FD).  Artificially create a pseudo
    // FD to ensure correct dispatch to generated code.  The 'volatile'
    // declaration is required to avoid the compiler from not observing the
    // alias of the pseudo FD to the function pointer, and hence, optimizing the
    // pseudo FD declaration/initialization away.
    volatile Address function_desc[] = {reinterpret_cast<Address>(fn_ptr_), 0,
                                        0};
    Signature* fn = reinterpret_cast<Signature*>(function_desc);
    return fn(args...);
#else
135
    return fn_ptr_(args...);
136
#endif  // V8_OS_AIX
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
  }
#endif

 private:
  friend class GeneratedCode<Return(Args...)>;
  Isolate* isolate_;
  Signature* fn_ptr_;
  GeneratedCode(Isolate* isolate, Signature* fn_ptr)
      : isolate_(isolate), fn_ptr_(fn_ptr) {}
};

// Allow to use {GeneratedCode<ret(arg1, arg2)>} instead of
// {GeneratedCode<ret, arg1, arg2>}.
template <typename Return, typename... Args>
class GeneratedCode<Return(Args...)> : public GeneratedCode<Return, Args...> {
 public:
  // Automatically convert from {GeneratedCode<ret, arg1, arg2>} to
  // {GeneratedCode<ret(arg1, arg2)>}.
  GeneratedCode(GeneratedCode<Return, Args...> other)
      : GeneratedCode<Return, Args...>(other.isolate_, other.fn_ptr_) {}
};
158 159 160 161

}  // namespace internal
}  // namespace v8

162
#endif  // V8_SIMULATOR_H_