summaryrefslogtreecommitdiff
path: root/deps/v8/src/simulator.h
blob: a7badaa6e506d55982c5bddecfdae7d0884724f3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// Copyright 2009 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_SIMULATOR_H_
#define V8_SIMULATOR_H_

#include "src/globals.h"
#include "src/objects/code.h"

#if V8_TARGET_ARCH_IA32
#include "src/ia32/simulator-ia32.h"
#elif V8_TARGET_ARCH_X64
#include "src/x64/simulator-x64.h"
#elif V8_TARGET_ARCH_ARM64
#include "src/arm64/simulator-arm64.h"
#elif V8_TARGET_ARCH_ARM
#include "src/arm/simulator-arm.h"
#elif V8_TARGET_ARCH_PPC
#include "src/ppc/simulator-ppc.h"
#elif V8_TARGET_ARCH_MIPS
#include "src/mips/simulator-mips.h"
#elif V8_TARGET_ARCH_MIPS64
#include "src/mips64/simulator-mips64.h"
#elif V8_TARGET_ARCH_S390
#include "src/s390/simulator-s390.h"
#else
#error Unsupported target architecture.
#endif

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);
  }

  static inline uintptr_t RegisterCTryCatch(v8::internal::Isolate* isolate,
                                            uintptr_t try_catch_address) {
    return Simulator::current(isolate)->PushAddress(try_catch_address);
  }

  static inline void UnregisterCTryCatch(v8::internal::Isolate* isolate) {
    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;
  }

  static inline uintptr_t RegisterCTryCatch(v8::internal::Isolate* isolate,
                                            uintptr_t try_catch_address) {
    USE(isolate);
    return try_catch_address;
  }

  static inline void UnregisterCTryCatch(v8::internal::Isolate* isolate) {
    USE(isolate);
  }
};

#endif  // defined(USE_SIMULATOR)

// 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...);

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

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

  static GeneratedCode FromCode(Code* code) {
    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>(
        reinterpret_cast<Address>(fn_ptr_), args...);
  }
#else
  DISABLE_CFI_ICALL Return Call(Args... args) {
    // When running without a simulator we call the entry directly.
    return fn_ptr_(args...);
  }
#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_) {}
};

}  // namespace internal
}  // namespace v8

#endif  // V8_SIMULATOR_H_