V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
register-configuration.cc
1 // Copyright 2014 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 #include "src/register-configuration.h"
6 #include "src/globals.h"
7 #include "src/macro-assembler.h"
8 
9 namespace v8 {
10 namespace internal {
11 
12 namespace {
13 
14 #define REGISTER_COUNT(R) 1 +
15 static const int kMaxAllocatableGeneralRegisterCount =
16  ALLOCATABLE_GENERAL_REGISTERS(REGISTER_COUNT)0;
17 static const int kMaxAllocatableDoubleRegisterCount =
18  ALLOCATABLE_DOUBLE_REGISTERS(REGISTER_COUNT)0;
19 
20 static const int kAllocatableGeneralCodes[] = {
21 #define REGISTER_CODE(R) kRegCode_##R,
22  ALLOCATABLE_GENERAL_REGISTERS(REGISTER_CODE)};
23 #undef REGISTER_CODE
24 
25 #define REGISTER_CODE(R) kDoubleCode_##R,
26 static const int kAllocatableDoubleCodes[] = {
27  ALLOCATABLE_DOUBLE_REGISTERS(REGISTER_CODE)};
28 #if V8_TARGET_ARCH_ARM
29 static const int kAllocatableNoVFP32DoubleCodes[] = {
30  ALLOCATABLE_NO_VFP32_DOUBLE_REGISTERS(REGISTER_CODE)};
31 #endif // V8_TARGET_ARCH_ARM
32 #undef REGISTER_CODE
33 
34 STATIC_ASSERT(RegisterConfiguration::kMaxGeneralRegisters >=
35  Register::kNumRegisters);
36 STATIC_ASSERT(RegisterConfiguration::kMaxFPRegisters >=
37  FloatRegister::kNumRegisters);
38 STATIC_ASSERT(RegisterConfiguration::kMaxFPRegisters >=
39  DoubleRegister::kNumRegisters);
40 STATIC_ASSERT(RegisterConfiguration::kMaxFPRegisters >=
41  Simd128Register::kNumRegisters);
42 
43 static int get_num_allocatable_double_registers() {
44  return
45 #if V8_TARGET_ARCH_IA32
46  kMaxAllocatableDoubleRegisterCount;
47 #elif V8_TARGET_ARCH_X64
48  kMaxAllocatableDoubleRegisterCount;
49 #elif V8_TARGET_ARCH_ARM
50  CpuFeatures::IsSupported(VFP32DREGS)
51  ? kMaxAllocatableDoubleRegisterCount
52  : (ALLOCATABLE_NO_VFP32_DOUBLE_REGISTERS(REGISTER_COUNT) 0);
53 #elif V8_TARGET_ARCH_ARM64
54  kMaxAllocatableDoubleRegisterCount;
55 #elif V8_TARGET_ARCH_MIPS
56  kMaxAllocatableDoubleRegisterCount;
57 #elif V8_TARGET_ARCH_MIPS64
58  kMaxAllocatableDoubleRegisterCount;
59 #elif V8_TARGET_ARCH_PPC
60  kMaxAllocatableDoubleRegisterCount;
61 #elif V8_TARGET_ARCH_S390
62  kMaxAllocatableDoubleRegisterCount;
63 #else
64 #error Unsupported target architecture.
65 #endif
66 }
67 
68 #undef REGISTER_COUNT
69 
70 static const int* get_allocatable_double_codes() {
71  return
72 #if V8_TARGET_ARCH_ARM
73  CpuFeatures::IsSupported(VFP32DREGS) ? kAllocatableDoubleCodes
74  : kAllocatableNoVFP32DoubleCodes;
75 #else
76  kAllocatableDoubleCodes;
77 #endif
78 }
79 
80 class ArchDefaultRegisterConfiguration : public RegisterConfiguration {
81  public:
82  ArchDefaultRegisterConfiguration()
83  : RegisterConfiguration(
84  Register::kNumRegisters, DoubleRegister::kNumRegisters,
85  kMaxAllocatableGeneralRegisterCount,
86  get_num_allocatable_double_registers(), kAllocatableGeneralCodes,
87  get_allocatable_double_codes(),
88  kSimpleFPAliasing ? AliasingKind::OVERLAP : AliasingKind::COMBINE) {
89  }
90 };
91 
92 struct RegisterConfigurationInitializer {
93  static void Construct(void* config) {
94  new (config) ArchDefaultRegisterConfiguration();
95  }
96 };
97 
98 static base::LazyInstance<ArchDefaultRegisterConfiguration,
99  RegisterConfigurationInitializer>::type
100  kDefaultRegisterConfiguration = LAZY_INSTANCE_INITIALIZER;
101 
102 // Allocatable registers with the masking register removed.
103 class ArchDefaultPoisoningRegisterConfiguration : public RegisterConfiguration {
104  public:
105  ArchDefaultPoisoningRegisterConfiguration()
106  : RegisterConfiguration(
107  Register::kNumRegisters, DoubleRegister::kNumRegisters,
108  kMaxAllocatableGeneralRegisterCount - 1,
109  get_num_allocatable_double_registers(),
110  InitializeGeneralRegisterCodes(), get_allocatable_double_codes(),
111  kSimpleFPAliasing ? AliasingKind::OVERLAP : AliasingKind::COMBINE) {
112  }
113 
114  private:
115  static const int* InitializeGeneralRegisterCodes() {
116  int filtered_index = 0;
117  for (int i = 0; i < kMaxAllocatableGeneralRegisterCount; ++i) {
118  if (kAllocatableGeneralCodes[i] != kSpeculationPoisonRegister.code()) {
119  allocatable_general_codes_[filtered_index] =
120  kAllocatableGeneralCodes[i];
121  filtered_index++;
122  }
123  }
124  DCHECK_EQ(filtered_index, kMaxAllocatableGeneralRegisterCount - 1);
125  return allocatable_general_codes_;
126  }
127 
128  static int
129  allocatable_general_codes_[kMaxAllocatableGeneralRegisterCount - 1];
130 };
131 
132 int ArchDefaultPoisoningRegisterConfiguration::allocatable_general_codes_
133  [kMaxAllocatableGeneralRegisterCount - 1];
134 
135 struct PoisoningRegisterConfigurationInitializer {
136  static void Construct(void* config) {
137  new (config) ArchDefaultPoisoningRegisterConfiguration();
138  }
139 };
140 
141 static base::LazyInstance<ArchDefaultPoisoningRegisterConfiguration,
142  PoisoningRegisterConfigurationInitializer>::type
143  kDefaultPoisoningRegisterConfiguration = LAZY_INSTANCE_INITIALIZER;
144 
145 // RestrictedRegisterConfiguration uses the subset of allocatable general
146 // registers the architecture support, which results into generating assembly
147 // to use less registers. Currently, it's only used by RecordWrite code stub.
148 class RestrictedRegisterConfiguration : public RegisterConfiguration {
149  public:
150  RestrictedRegisterConfiguration(
151  int num_allocatable_general_registers,
152  std::unique_ptr<int[]> allocatable_general_register_codes,
153  std::unique_ptr<char const* []> allocatable_general_register_names)
154  : RegisterConfiguration(
155  Register::kNumRegisters, DoubleRegister::kNumRegisters,
156  num_allocatable_general_registers,
157  get_num_allocatable_double_registers(),
158  allocatable_general_register_codes.get(),
159  get_allocatable_double_codes(),
160  kSimpleFPAliasing ? AliasingKind::OVERLAP : AliasingKind::COMBINE),
161  allocatable_general_register_codes_(
162  std::move(allocatable_general_register_codes)),
163  allocatable_general_register_names_(
164  std::move(allocatable_general_register_names)) {
165  for (int i = 0; i < num_allocatable_general_registers; ++i) {
166  DCHECK(
167  IsAllocatableGeneralRegister(allocatable_general_register_codes_[i]));
168  }
169  }
170 
171  bool IsAllocatableGeneralRegister(int code) {
172  for (int i = 0; i < kMaxAllocatableGeneralRegisterCount; ++i) {
173  if (code == kAllocatableGeneralCodes[i]) {
174  return true;
175  }
176  }
177  return false;
178  }
179 
180  private:
181  std::unique_ptr<int[]> allocatable_general_register_codes_;
182  std::unique_ptr<char const* []> allocatable_general_register_names_;
183 };
184 
185 } // namespace
186 
187 const RegisterConfiguration* RegisterConfiguration::Default() {
188  return &kDefaultRegisterConfiguration.Get();
189 }
190 
191 const RegisterConfiguration* RegisterConfiguration::Poisoning() {
192  return &kDefaultPoisoningRegisterConfiguration.Get();
193 }
194 
195 const RegisterConfiguration* RegisterConfiguration::RestrictGeneralRegisters(
196  RegList registers) {
197  int num = NumRegs(registers);
198  std::unique_ptr<int[]> codes{new int[num]};
199  std::unique_ptr<char const* []> names { new char const*[num] };
200  int counter = 0;
201  for (int i = 0; i < Default()->num_allocatable_general_registers(); ++i) {
202  auto reg = Register::from_code(Default()->GetAllocatableGeneralCode(i));
203  if (reg.bit() & registers) {
204  DCHECK(counter < num);
205  codes[counter] = reg.code();
206  names[counter] = RegisterName(Register::from_code(i));
207  counter++;
208  }
209  }
210 
211  return new RestrictedRegisterConfiguration(num, std::move(codes),
212  std::move(names));
213 }
214 
215 RegisterConfiguration::RegisterConfiguration(
216  int num_general_registers, int num_double_registers,
217  int num_allocatable_general_registers, int num_allocatable_double_registers,
218  const int* allocatable_general_codes, const int* allocatable_double_codes,
219  AliasingKind fp_aliasing_kind)
220  : num_general_registers_(num_general_registers),
221  num_float_registers_(0),
222  num_double_registers_(num_double_registers),
223  num_simd128_registers_(0),
224  num_allocatable_general_registers_(num_allocatable_general_registers),
225  num_allocatable_float_registers_(0),
226  num_allocatable_double_registers_(num_allocatable_double_registers),
227  num_allocatable_simd128_registers_(0),
228  allocatable_general_codes_mask_(0),
229  allocatable_float_codes_mask_(0),
230  allocatable_double_codes_mask_(0),
231  allocatable_simd128_codes_mask_(0),
232  allocatable_general_codes_(allocatable_general_codes),
233  allocatable_double_codes_(allocatable_double_codes),
234  fp_aliasing_kind_(fp_aliasing_kind) {
235  DCHECK_LE(num_general_registers_,
236  RegisterConfiguration::kMaxGeneralRegisters);
237  DCHECK_LE(num_double_registers_, RegisterConfiguration::kMaxFPRegisters);
238  for (int i = 0; i < num_allocatable_general_registers_; ++i) {
239  allocatable_general_codes_mask_ |= (1 << allocatable_general_codes_[i]);
240  }
241  for (int i = 0; i < num_allocatable_double_registers_; ++i) {
242  allocatable_double_codes_mask_ |= (1 << allocatable_double_codes_[i]);
243  }
244 
245  if (fp_aliasing_kind_ == COMBINE) {
246  num_float_registers_ = num_double_registers_ * 2 <= kMaxFPRegisters
247  ? num_double_registers_ * 2
248  : kMaxFPRegisters;
249  num_allocatable_float_registers_ = 0;
250  for (int i = 0; i < num_allocatable_double_registers_; i++) {
251  int base_code = allocatable_double_codes_[i] * 2;
252  if (base_code >= kMaxFPRegisters) continue;
253  allocatable_float_codes_[num_allocatable_float_registers_++] = base_code;
254  allocatable_float_codes_[num_allocatable_float_registers_++] =
255  base_code + 1;
256  allocatable_float_codes_mask_ |= (0x3 << base_code);
257  }
258  num_simd128_registers_ = num_double_registers_ / 2;
259  num_allocatable_simd128_registers_ = 0;
260  int last_simd128_code = allocatable_double_codes_[0] / 2;
261  for (int i = 1; i < num_allocatable_double_registers_; i++) {
262  int next_simd128_code = allocatable_double_codes_[i] / 2;
263  // This scheme assumes allocatable_double_codes_ are strictly increasing.
264  DCHECK_GE(next_simd128_code, last_simd128_code);
265  if (last_simd128_code == next_simd128_code) {
266  allocatable_simd128_codes_[num_allocatable_simd128_registers_++] =
267  next_simd128_code;
268  allocatable_simd128_codes_mask_ |= (0x1 << next_simd128_code);
269  }
270  last_simd128_code = next_simd128_code;
271  }
272  } else {
273  DCHECK(fp_aliasing_kind_ == OVERLAP);
274  num_float_registers_ = num_simd128_registers_ = num_double_registers_;
275  num_allocatable_float_registers_ = num_allocatable_simd128_registers_ =
276  num_allocatable_double_registers_;
277  for (int i = 0; i < num_allocatable_float_registers_; ++i) {
278  allocatable_float_codes_[i] = allocatable_simd128_codes_[i] =
279  allocatable_double_codes_[i];
280  }
281  allocatable_float_codes_mask_ = allocatable_simd128_codes_mask_ =
282  allocatable_double_codes_mask_;
283  }
284 }
285 
286 // Assert that kFloat32, kFloat64, and kSimd128 are consecutive values.
287 STATIC_ASSERT(static_cast<int>(MachineRepresentation::kSimd128) ==
288  static_cast<int>(MachineRepresentation::kFloat64) + 1);
289 STATIC_ASSERT(static_cast<int>(MachineRepresentation::kFloat64) ==
290  static_cast<int>(MachineRepresentation::kFloat32) + 1);
291 
292 int RegisterConfiguration::GetAliases(MachineRepresentation rep, int index,
293  MachineRepresentation other_rep,
294  int* alias_base_index) const {
295  DCHECK(fp_aliasing_kind_ == COMBINE);
296  DCHECK(IsFloatingPoint(rep) && IsFloatingPoint(other_rep));
297  if (rep == other_rep) {
298  *alias_base_index = index;
299  return 1;
300  }
301  int rep_int = static_cast<int>(rep);
302  int other_rep_int = static_cast<int>(other_rep);
303  if (rep_int > other_rep_int) {
304  int shift = rep_int - other_rep_int;
305  int base_index = index << shift;
306  if (base_index >= kMaxFPRegisters) {
307  // Alias indices would be out of FP register range.
308  return 0;
309  }
310  *alias_base_index = base_index;
311  return 1 << shift;
312  }
313  int shift = other_rep_int - rep_int;
314  *alias_base_index = index >> shift;
315  return 1;
316 }
317 
318 bool RegisterConfiguration::AreAliases(MachineRepresentation rep, int index,
319  MachineRepresentation other_rep,
320  int other_index) const {
321  DCHECK(fp_aliasing_kind_ == COMBINE);
322  DCHECK(IsFloatingPoint(rep) && IsFloatingPoint(other_rep));
323  if (rep == other_rep) {
324  return index == other_index;
325  }
326  int rep_int = static_cast<int>(rep);
327  int other_rep_int = static_cast<int>(other_rep);
328  if (rep_int > other_rep_int) {
329  int shift = rep_int - other_rep_int;
330  return index == other_index >> shift;
331  }
332  int shift = other_rep_int - rep_int;
333  return index >> shift == other_index;
334 }
335 
336 } // namespace internal
337 } // namespace v8
STL namespace.
Definition: libplatform.h:13