tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

testJitRegisterSet.cpp (6095B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
      2 * vim: set ts=8 sts=2 et sw=2 tw=80:
      3 */
      4 /* This Source Code Form is subject to the terms of the Mozilla Public
      5 * License, v. 2.0. If a copy of the MPL was not distributed with this
      6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      7 
      8 #include "jit/RegisterSets.h"
      9 
     10 #include "jsapi-tests/tests.h"
     11 
     12 using namespace js;
     13 using namespace js::jit;
     14 
     15 static bool CoPrime(size_t a, size_t b) {
     16  if (b <= 1) {
     17    return a == 1 || b == 1;
     18  }
     19  return CoPrime(b, a % b);
     20 }
     21 
     22 // This macros are use to iterave over all registers in a large number of
     23 // non-looping sequences, which does not rely on the getFirst / getLast
     24 // functions.
     25 #define BEGIN_INDEX_WALK(RegTotal)                      \
     26  static const size_t Total = RegTotal;                 \
     27  for (size_t walk = 1; walk < RegTotal; walk += 2) {   \
     28    if (!CoPrime(RegTotal, walk)) continue;             \
     29    for (size_t start = 0; start < RegTotal; start++) { \
     30      size_t index = start;
     31 
     32 #define END_INDEX_WALK \
     33  }                    \
     34  }
     35 
     36 #define BEGIN_All_WALK(RegTotal)        \
     37  static const size_t Total = RegTotal; \
     38  size_t walk = 1;                      \
     39  size_t start = 0;                     \
     40  size_t index = start;
     41 
     42 #define FOR_ALL_REGISTERS(Register, reg) \
     43  do {                                   \
     44    Register reg = Register::FromCode(index);
     45 
     46 #define END_FOR_ALL_REGISTERS     \
     47  index = (index + walk) % Total; \
     48  }                               \
     49  while (index != start)
     50 
     51 BEGIN_TEST(testJitRegisterSet_GPR) {
     52  BEGIN_INDEX_WALK(Registers::Total)
     53 
     54  LiveGeneralRegisterSet liveRegs;
     55  AllocatableGeneralRegisterSet pool(GeneralRegisterSet::All());
     56  CHECK(liveRegs.empty());
     57  CHECK(pool.set() == GeneralRegisterSet::All());
     58 
     59  FOR_ALL_REGISTERS(Register, reg) {
     60    CHECK(!pool.has(reg) || !liveRegs.has(reg));
     61    if (pool.has(reg)) {
     62      CHECK(!liveRegs.has(reg));
     63      pool.take(reg);
     64      liveRegs.add(reg);
     65      CHECK(liveRegs.has(reg));
     66      CHECK(!pool.has(reg));
     67    }
     68    CHECK(!pool.has(reg) || !liveRegs.has(reg));
     69  }
     70  END_FOR_ALL_REGISTERS;
     71 
     72  CHECK(pool.empty());
     73 
     74  FOR_ALL_REGISTERS(Register, reg) {
     75    CHECK(!pool.has(reg) || !liveRegs.has(reg));
     76    if (liveRegs.has(reg)) {
     77      CHECK(!pool.has(reg));
     78      liveRegs.take(reg);
     79      pool.add(reg);
     80      CHECK(pool.has(reg));
     81      CHECK(!liveRegs.has(reg));
     82    }
     83    CHECK(!pool.has(reg) || !liveRegs.has(reg));
     84  }
     85  END_FOR_ALL_REGISTERS;
     86 
     87  CHECK(liveRegs.empty());
     88  CHECK(pool.set() == GeneralRegisterSet::All());
     89 
     90  END_INDEX_WALK
     91  return true;
     92 }
     93 END_TEST(testJitRegisterSet_GPR)
     94 
     95 BEGIN_TEST(testJitRegisterSet_FPU) {
     96  BEGIN_INDEX_WALK(FloatRegisters::Total)
     97 
     98  LiveFloatRegisterSet liveRegs;
     99  AllocatableFloatRegisterSet pool(FloatRegisterSet::All());
    100  CHECK(liveRegs.empty());
    101  CHECK(pool.set() == FloatRegisterSet::All());
    102 
    103  FOR_ALL_REGISTERS(FloatRegister, reg) {
    104    CHECK(!pool.has(reg) || !liveRegs.has(reg));
    105    if (pool.has(reg)) {
    106      CHECK(!liveRegs.has(reg));
    107      pool.take(reg);
    108      liveRegs.add(reg);
    109      CHECK(liveRegs.has(reg));
    110      CHECK(!pool.has(reg));
    111    }
    112    CHECK(!pool.has(reg) || !liveRegs.has(reg));
    113  }
    114  END_FOR_ALL_REGISTERS;
    115 
    116  CHECK(pool.empty());
    117 
    118  FOR_ALL_REGISTERS(FloatRegister, reg) {
    119    CHECK(!pool.has(reg) || !liveRegs.has(reg));
    120    if (liveRegs.has(reg)) {
    121      CHECK(!pool.has(reg));
    122      liveRegs.take(reg);
    123      pool.add(reg);
    124      CHECK(pool.has(reg));
    125      CHECK(!liveRegs.has(reg));
    126    }
    127    CHECK(!pool.has(reg) || !liveRegs.has(reg));
    128  }
    129  END_FOR_ALL_REGISTERS;
    130 
    131  CHECK(liveRegs.empty());
    132  CHECK(pool.set() == FloatRegisterSet::All());
    133 
    134  END_INDEX_WALK
    135  return true;
    136 }
    137 END_TEST(testJitRegisterSet_FPU)
    138 
    139 void pullAllFpus(AllocatableFloatRegisterSet& set, uint32_t& max_bits,
    140                 uint32_t bits) {
    141  FloatRegisterSet allocSet(set.bits());
    142  FloatRegisterSet available_f32(
    143      allocSet.allAllocatable<RegTypeName::Float32>());
    144  FloatRegisterSet available_f64(
    145      allocSet.allAllocatable<RegTypeName::Float64>());
    146  FloatRegisterSet available_v128(
    147      allocSet.allAllocatable<RegTypeName::Vector128>());
    148  for (FloatRegisterIterator it(available_f32); it.more(); ++it) {
    149    FloatRegister tmp = *it;
    150    set.take(tmp);
    151    pullAllFpus(set, max_bits, bits + 32);
    152    set.add(tmp);
    153  }
    154  for (FloatRegisterIterator it(available_f64); it.more(); ++it) {
    155    FloatRegister tmp = *it;
    156    set.take(tmp);
    157    pullAllFpus(set, max_bits, bits + 64);
    158    set.add(tmp);
    159  }
    160  for (FloatRegisterIterator it(available_v128); it.more(); ++it) {
    161    FloatRegister tmp = *it;
    162    set.take(tmp);
    163    pullAllFpus(set, max_bits, bits + 128);
    164    set.add(tmp);
    165  }
    166  if (bits >= max_bits) {
    167    max_bits = bits;
    168  }
    169 }
    170 
    171 // TODO: MIPS64 only allows calling |alignedAliased| for Double FP registers.
    172 // Disable this test for MIPS64 until it's clear that that restriction is
    173 // actually correct. (bug 1993738)
    174 #ifndef JS_CODEGEN_MIPS64
    175 BEGIN_TEST(testJitRegisterSet_FPU_Aliases) {
    176  BEGIN_All_WALK(FloatRegisters::Total);
    177  FOR_ALL_REGISTERS(FloatRegister, reg) {
    178    AllocatableFloatRegisterSet pool;
    179    pool.add(reg);
    180 
    181    uint32_t alias_bits = 0;
    182    for (uint32_t i = 0; i < reg.numAlignedAliased(); i++) {
    183      FloatRegister alias = reg.alignedAliased(i);
    184 
    185      if (alias.isSingle()) {
    186        if (alias_bits <= 32) {
    187          alias_bits = 32;
    188        }
    189      } else if (alias.isDouble()) {
    190        if (alias_bits <= 64) {
    191          alias_bits = 64;
    192        }
    193      } else if (alias.isSimd128()) {
    194        if (alias_bits <= 128) {
    195          alias_bits = 128;
    196        }
    197      }
    198    }
    199 
    200    uint32_t max_bits = 0;
    201    pullAllFpus(pool, max_bits, 0);
    202 
    203    // By adding one register, we expect that we should not be able to pull
    204    // more than any of its aligned aliases.  This rule should hold for both
    205    // x64 and ARM.
    206    CHECK(max_bits <= alias_bits);
    207 
    208    // We added one register, we expect to be able to pull it back.
    209    CHECK(max_bits > 0);
    210  }
    211  END_FOR_ALL_REGISTERS;
    212 
    213  return true;
    214 }
    215 END_TEST(testJitRegisterSet_FPU_Aliases)
    216 #endif