• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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) Register::kCode_##R,
22     ALLOCATABLE_GENERAL_REGISTERS(REGISTER_CODE)};
23 #undef REGISTER_CODE
24 
25 static const int kAllocatableDoubleCodes[] = {
26 #define REGISTER_CODE(R) DoubleRegister::kCode_##R,
27     ALLOCATABLE_DOUBLE_REGISTERS(REGISTER_CODE)};
28 #undef REGISTER_CODE
29 
30 static const char* const kGeneralRegisterNames[] = {
31 #define REGISTER_NAME(R) #R,
32     GENERAL_REGISTERS(REGISTER_NAME)
33 #undef REGISTER_NAME
34 };
35 
36 static const char* const kFloatRegisterNames[] = {
37 #define REGISTER_NAME(R) #R,
38     FLOAT_REGISTERS(REGISTER_NAME)
39 #undef REGISTER_NAME
40 };
41 
42 static const char* const kDoubleRegisterNames[] = {
43 #define REGISTER_NAME(R) #R,
44     DOUBLE_REGISTERS(REGISTER_NAME)
45 #undef REGISTER_NAME
46 };
47 
48 static const char* const kSimd128RegisterNames[] = {
49 #define REGISTER_NAME(R) #R,
50     SIMD128_REGISTERS(REGISTER_NAME)
51 #undef REGISTER_NAME
52 };
53 
54 STATIC_ASSERT(RegisterConfiguration::kMaxGeneralRegisters >=
55               Register::kNumRegisters);
56 STATIC_ASSERT(RegisterConfiguration::kMaxFPRegisters >=
57               FloatRegister::kMaxNumRegisters);
58 STATIC_ASSERT(RegisterConfiguration::kMaxFPRegisters >=
59               DoubleRegister::kMaxNumRegisters);
60 STATIC_ASSERT(RegisterConfiguration::kMaxFPRegisters >=
61               Simd128Register::kMaxNumRegisters);
62 
63 enum CompilerSelector { CRANKSHAFT, TURBOFAN };
64 
65 class ArchDefaultRegisterConfiguration : public RegisterConfiguration {
66  public:
ArchDefaultRegisterConfiguration(CompilerSelector compiler)67   explicit ArchDefaultRegisterConfiguration(CompilerSelector compiler)
68       : RegisterConfiguration(
69             Register::kNumRegisters, DoubleRegister::kMaxNumRegisters,
70 #if V8_TARGET_ARCH_IA32
71             kMaxAllocatableGeneralRegisterCount,
72             kMaxAllocatableDoubleRegisterCount,
73 #elif V8_TARGET_ARCH_X87
74             kMaxAllocatableGeneralRegisterCount,
75             compiler == TURBOFAN ? 1 : kMaxAllocatableDoubleRegisterCount,
76 #elif V8_TARGET_ARCH_X64
77             kMaxAllocatableGeneralRegisterCount,
78             kMaxAllocatableDoubleRegisterCount,
79 #elif V8_TARGET_ARCH_ARM
80             FLAG_enable_embedded_constant_pool
81                 ? (kMaxAllocatableGeneralRegisterCount - 1)
82                 : kMaxAllocatableGeneralRegisterCount,
83             CpuFeatures::IsSupported(VFP32DREGS)
84                 ? kMaxAllocatableDoubleRegisterCount
85                 : (ALLOCATABLE_NO_VFP32_DOUBLE_REGISTERS(REGISTER_COUNT) 0),
86 #elif V8_TARGET_ARCH_ARM64
87             kMaxAllocatableGeneralRegisterCount,
88             kMaxAllocatableDoubleRegisterCount,
89 #elif V8_TARGET_ARCH_MIPS
90             kMaxAllocatableGeneralRegisterCount,
91             kMaxAllocatableDoubleRegisterCount,
92 #elif V8_TARGET_ARCH_MIPS64
93             kMaxAllocatableGeneralRegisterCount,
94             kMaxAllocatableDoubleRegisterCount,
95 #elif V8_TARGET_ARCH_PPC
96             kMaxAllocatableGeneralRegisterCount,
97             kMaxAllocatableDoubleRegisterCount,
98 #elif V8_TARGET_ARCH_S390
99             kMaxAllocatableGeneralRegisterCount,
100             kMaxAllocatableDoubleRegisterCount,
101 #else
102 #error Unsupported target architecture.
103 #endif
104             kAllocatableGeneralCodes, kAllocatableDoubleCodes,
105             kSimpleFPAliasing ? AliasingKind::OVERLAP : AliasingKind::COMBINE,
106             kGeneralRegisterNames, kFloatRegisterNames, kDoubleRegisterNames,
107             kSimd128RegisterNames) {
108   }
109 };
110 
111 template <CompilerSelector compiler>
112 struct RegisterConfigurationInitializer {
Constructv8::internal::__anonf84f25400111::RegisterConfigurationInitializer113   static void Construct(ArchDefaultRegisterConfiguration* config) {
114     new (config) ArchDefaultRegisterConfiguration(compiler);
115   }
116 };
117 
118 static base::LazyInstance<ArchDefaultRegisterConfiguration,
119                           RegisterConfigurationInitializer<CRANKSHAFT>>::type
120     kDefaultRegisterConfigurationForCrankshaft = LAZY_INSTANCE_INITIALIZER;
121 
122 static base::LazyInstance<ArchDefaultRegisterConfiguration,
123                           RegisterConfigurationInitializer<TURBOFAN>>::type
124     kDefaultRegisterConfigurationForTurboFan = LAZY_INSTANCE_INITIALIZER;
125 
126 }  // namespace
127 
Crankshaft()128 const RegisterConfiguration* RegisterConfiguration::Crankshaft() {
129   return &kDefaultRegisterConfigurationForCrankshaft.Get();
130 }
131 
Turbofan()132 const RegisterConfiguration* RegisterConfiguration::Turbofan() {
133   return &kDefaultRegisterConfigurationForTurboFan.Get();
134 }
135 
RegisterConfiguration(int num_general_registers,int num_double_registers,int num_allocatable_general_registers,int num_allocatable_double_registers,const int * allocatable_general_codes,const int * allocatable_double_codes,AliasingKind fp_aliasing_kind,const char * const * general_register_names,const char * const * float_register_names,const char * const * double_register_names,const char * const * simd128_register_names)136 RegisterConfiguration::RegisterConfiguration(
137     int num_general_registers, int num_double_registers,
138     int num_allocatable_general_registers, int num_allocatable_double_registers,
139     const int* allocatable_general_codes, const int* allocatable_double_codes,
140     AliasingKind fp_aliasing_kind, const char* const* general_register_names,
141     const char* const* float_register_names,
142     const char* const* double_register_names,
143     const char* const* simd128_register_names)
144     : num_general_registers_(num_general_registers),
145       num_float_registers_(0),
146       num_double_registers_(num_double_registers),
147       num_simd128_registers_(0),
148       num_allocatable_general_registers_(num_allocatable_general_registers),
149       num_allocatable_float_registers_(0),
150       num_allocatable_double_registers_(num_allocatable_double_registers),
151       num_allocatable_simd128_registers_(0),
152       allocatable_general_codes_mask_(0),
153       allocatable_float_codes_mask_(0),
154       allocatable_double_codes_mask_(0),
155       allocatable_simd128_codes_mask_(0),
156       allocatable_general_codes_(allocatable_general_codes),
157       allocatable_double_codes_(allocatable_double_codes),
158       fp_aliasing_kind_(fp_aliasing_kind),
159       general_register_names_(general_register_names),
160       float_register_names_(float_register_names),
161       double_register_names_(double_register_names),
162       simd128_register_names_(simd128_register_names) {
163   DCHECK(num_general_registers_ <= RegisterConfiguration::kMaxGeneralRegisters);
164   DCHECK(num_double_registers_ <= RegisterConfiguration::kMaxFPRegisters);
165   for (int i = 0; i < num_allocatable_general_registers_; ++i) {
166     allocatable_general_codes_mask_ |= (1 << allocatable_general_codes_[i]);
167   }
168   for (int i = 0; i < num_allocatable_double_registers_; ++i) {
169     allocatable_double_codes_mask_ |= (1 << allocatable_double_codes_[i]);
170   }
171 
172   if (fp_aliasing_kind_ == COMBINE) {
173     num_float_registers_ = num_double_registers_ * 2 <= kMaxFPRegisters
174                                ? num_double_registers_ * 2
175                                : kMaxFPRegisters;
176     num_allocatable_float_registers_ = 0;
177     for (int i = 0; i < num_allocatable_double_registers_; i++) {
178       int base_code = allocatable_double_codes_[i] * 2;
179       if (base_code >= kMaxFPRegisters) continue;
180       allocatable_float_codes_[num_allocatable_float_registers_++] = base_code;
181       allocatable_float_codes_[num_allocatable_float_registers_++] =
182           base_code + 1;
183       allocatable_float_codes_mask_ |= (0x3 << base_code);
184     }
185     num_simd128_registers_ = num_double_registers_ / 2;
186     num_allocatable_simd128_registers_ = 0;
187     int last_simd128_code = allocatable_double_codes_[0] / 2;
188     for (int i = 1; i < num_allocatable_double_registers_; i++) {
189       int next_simd128_code = allocatable_double_codes_[i] / 2;
190       // This scheme assumes allocatable_double_codes_ are strictly increasing.
191       DCHECK_GE(next_simd128_code, last_simd128_code);
192       if (last_simd128_code == next_simd128_code) {
193         allocatable_simd128_codes_[num_allocatable_simd128_registers_++] =
194             next_simd128_code;
195         allocatable_simd128_codes_mask_ |= (0x1 << next_simd128_code);
196       }
197       last_simd128_code = next_simd128_code;
198     }
199   } else {
200     DCHECK(fp_aliasing_kind_ == OVERLAP);
201     num_float_registers_ = num_simd128_registers_ = num_double_registers_;
202     num_allocatable_float_registers_ = num_allocatable_simd128_registers_ =
203         num_allocatable_double_registers_;
204     for (int i = 0; i < num_allocatable_float_registers_; ++i) {
205       allocatable_float_codes_[i] = allocatable_simd128_codes_[i] =
206           allocatable_double_codes_[i];
207     }
208     allocatable_float_codes_mask_ = allocatable_simd128_codes_mask_ =
209         allocatable_double_codes_mask_;
210   }
211 }
212 
213 // Assert that kFloat32, kFloat64, and kSimd128 are consecutive values.
214 STATIC_ASSERT(static_cast<int>(MachineRepresentation::kSimd128) ==
215               static_cast<int>(MachineRepresentation::kFloat64) + 1);
216 STATIC_ASSERT(static_cast<int>(MachineRepresentation::kFloat64) ==
217               static_cast<int>(MachineRepresentation::kFloat32) + 1);
218 
GetAliases(MachineRepresentation rep,int index,MachineRepresentation other_rep,int * alias_base_index) const219 int RegisterConfiguration::GetAliases(MachineRepresentation rep, int index,
220                                       MachineRepresentation other_rep,
221                                       int* alias_base_index) const {
222   DCHECK(fp_aliasing_kind_ == COMBINE);
223   DCHECK(IsFloatingPoint(rep) && IsFloatingPoint(other_rep));
224   if (rep == other_rep) {
225     *alias_base_index = index;
226     return 1;
227   }
228   int rep_int = static_cast<int>(rep);
229   int other_rep_int = static_cast<int>(other_rep);
230   if (rep_int > other_rep_int) {
231     int shift = rep_int - other_rep_int;
232     int base_index = index << shift;
233     if (base_index >= kMaxFPRegisters) {
234       // Alias indices would be out of FP register range.
235       return 0;
236     }
237     *alias_base_index = base_index;
238     return 1 << shift;
239   }
240   int shift = other_rep_int - rep_int;
241   *alias_base_index = index >> shift;
242   return 1;
243 }
244 
AreAliases(MachineRepresentation rep,int index,MachineRepresentation other_rep,int other_index) const245 bool RegisterConfiguration::AreAliases(MachineRepresentation rep, int index,
246                                        MachineRepresentation other_rep,
247                                        int other_index) const {
248   DCHECK(fp_aliasing_kind_ == COMBINE);
249   DCHECK(IsFloatingPoint(rep) && IsFloatingPoint(other_rep));
250   if (rep == other_rep) {
251     return index == other_index;
252   }
253   int rep_int = static_cast<int>(rep);
254   int other_rep_int = static_cast<int>(other_rep);
255   if (rep_int > other_rep_int) {
256     int shift = rep_int - other_rep_int;
257     return index == other_index >> shift;
258   }
259   int shift = other_rep_int - rep_int;
260   return index >> shift == other_index;
261 }
262 
263 #undef REGISTER_COUNT
264 
265 }  // namespace internal
266 }  // namespace v8
267