LCOV - code coverage report
Current view: top level - src - register-configuration.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 70 71 98.6 %
Date: 2017-10-20 Functions: 9 11 81.8 %

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

Generated by: LCOV version 1.10