[vm] Fix kNumberOfReservedCpuRegisters on ARM64

Instead of using an integer literal use constexpr popcount
function instead.

The misalignment causes an incorrect generation of a call
to a shared write barrier stub for the last allocatable register
on ARM64.

Reported by Lin Zuojian <zuojian.lzj@alibaba-inc.com>

TEST=ci

Change-Id: I69ce32da958573be0ec8967e462f8a378a778a28
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/254401
Commit-Queue: Slava Egorov <vegorov@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
Vyacheslav Egorov 2022-08-10 18:04:09 +00:00 committed by Commit Bot
parent d23c1b9d88
commit afb34fb9e3
7 changed files with 281 additions and 278 deletions

View file

@ -29,34 +29,6 @@ uintptr_t Utils::RoundUpToPowerOfTwo(uintptr_t x) {
return x + 1;
}
int Utils::CountOneBits64(uint64_t x) {
// Apparently there are x64 chips without popcount.
#if __GNUC__ && !defined(HOST_ARCH_IA32) && !defined(HOST_ARCH_X64)
return __builtin_popcountll(x);
#else
x = x - ((x >> 1) & 0x5555555555555555);
x = (x & 0x3333333333333333) + ((x >> 2) & 0x3333333333333333);
x = (((x + (x >> 4)) & 0x0f0f0f0f0f0f0f0f) * 0x0101010101010101) >> 56;
return x;
#endif
}
int Utils::CountOneBits32(uint32_t x) {
// Apparently there are x64 chips without popcount.
#if __GNUC__ && !defined(HOST_ARCH_IA32) && !defined(HOST_ARCH_X64)
return __builtin_popcount(x);
#else
// Implementation is from "Hacker's Delight" by Henry S. Warren, Jr.,
// figure 5-2, page 66, where the function is called pop.
x = x - ((x >> 1) & 0x55555555);
x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
x = (x + (x >> 4)) & 0x0F0F0F0F;
x = x + (x >> 8);
x = x + (x >> 16);
return static_cast<int>(x & 0x0000003F);
#endif
}
int Utils::CountLeadingZeros64(uint64_t x) {
#if defined(ARCH_IS_32_BIT)
const uint32_t x_hi = static_cast<uint32_t>(x >> 32);
@ -110,21 +82,21 @@ int Utils::CountTrailingZeros32(uint32_t x) {
}
uint64_t Utils::ReverseBits64(uint64_t x) {
x = ( (x >> 32) & 0x00000000ffffffff ) | ( x << 32 );
x = ( (x >> 16) & 0x0000ffff0000ffff ) | ( (x & 0x0000ffff0000ffff) << 16 );
x = ( (x >> 8) & 0x00ff00ff00ff00ff ) | ( (x & 0x00ff00ff00ff00ff) << 8 );
x = ( (x >> 4) & 0x0f0f0f0f0f0f0f0f ) | ( (x & 0x0f0f0f0f0f0f0f0f) << 4 );
x = ( (x >> 2) & 0x3333333333333333 ) | ( (x & 0x3333333333333333) << 2 );
x = ( (x >> 1) & 0x5555555555555555 ) | ( (x & 0x5555555555555555) << 1 );
x = ((x >> 32) & 0x00000000ffffffff) | (x << 32);
x = ((x >> 16) & 0x0000ffff0000ffff) | ((x & 0x0000ffff0000ffff) << 16);
x = ((x >> 8) & 0x00ff00ff00ff00ff) | ((x & 0x00ff00ff00ff00ff) << 8);
x = ((x >> 4) & 0x0f0f0f0f0f0f0f0f) | ((x & 0x0f0f0f0f0f0f0f0f) << 4);
x = ((x >> 2) & 0x3333333333333333) | ((x & 0x3333333333333333) << 2);
x = ((x >> 1) & 0x5555555555555555) | ((x & 0x5555555555555555) << 1);
return x;
}
uint32_t Utils::ReverseBits32(uint32_t x) {
x = ( (x >> 16) & 0x0000ffff ) | ( (x & 0x0000ffff) << 16 );
x = ( (x >> 8) & 0x00ff00ff ) | ( (x & 0x00ff00ff) << 8 );
x = ( (x >> 4) & 0x0f0f0f0f ) | ( (x & 0x0f0f0f0f) << 4 );
x = ( (x >> 2) & 0x33333333 ) | ( (x & 0x33333333) << 2 );
x = ( (x >> 1) & 0x55555555 ) | ( (x & 0x55555555) << 1 );
x = ((x >> 16) & 0x0000ffff) | ((x & 0x0000ffff) << 16);
x = ((x >> 8) & 0x00ff00ff) | ((x & 0x00ff00ff) << 8);
x = ((x >> 4) & 0x0f0f0f0f) | ((x & 0x0f0f0f0f) << 4);
x = ((x >> 2) & 0x33333333) | ((x & 0x33333333) << 2);
x = ((x >> 1) & 0x55555555) | ((x & 0x55555555) << 1);
return x;
}

View file

@ -106,10 +106,35 @@ class Utils {
static uintptr_t RoundUpToPowerOfTwo(uintptr_t x);
static int CountOneBits64(uint64_t x);
static int CountOneBits32(uint32_t x);
static constexpr int CountOneBits64(uint64_t x) {
// Apparently there are x64 chips without popcount.
#if __GNUC__ && !defined(HOST_ARCH_IA32) && !defined(HOST_ARCH_X64)
return __builtin_popcountll(x);
#else
x = x - ((x >> 1) & 0x5555555555555555);
x = (x & 0x3333333333333333) + ((x >> 2) & 0x3333333333333333);
x = (((x + (x >> 4)) & 0x0f0f0f0f0f0f0f0f) * 0x0101010101010101) >> 56;
return x;
#endif
}
static int CountOneBitsWord(uword x) {
static constexpr int CountOneBits32(uint32_t x) {
// Apparently there are x64 chips without popcount.
#if __GNUC__ && !defined(HOST_ARCH_IA32) && !defined(HOST_ARCH_X64)
return __builtin_popcount(x);
#else
// Implementation is from "Hacker's Delight" by Henry S. Warren, Jr.,
// figure 5-2, page 66, where the function is called pop.
x = x - ((x >> 1) & 0x55555555);
x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
x = (x + (x >> 4)) & 0x0F0F0F0F;
x = x + (x >> 8);
x = x + (x >> 16);
return static_cast<int>(x & 0x0000003F);
#endif
}
static constexpr int CountOneBitsWord(uword x) {
#ifdef ARCH_IS_64_BIT
return CountOneBits64(x);
#else

File diff suppressed because it is too large Load diff

View file

@ -11,6 +11,7 @@
#include "platform/assert.h"
#include "platform/globals.h"
#include "platform/utils.h"
#include "vm/constants_base.h"
@ -625,7 +626,8 @@ const int kAbiPreservedFpuRegCount = 4;
const RegList kReservedCpuRegisters = (1 << SPREG) | (1 << FPREG) | (1 << TMP) |
(1 << PP) | (1 << THR) | (1 << LR) |
(1 << PC) | (1 << NOTFP);
constexpr intptr_t kNumberOfReservedCpuRegisters = 8;
constexpr intptr_t kNumberOfReservedCpuRegisters =
Utils::CountOneBits32(kReservedCpuRegisters);
// CPU registers available to Dart allocator.
constexpr RegList kDartAvailableCpuRegs =
kAllCpuRegistersList & ~kReservedCpuRegisters;

View file

@ -11,6 +11,7 @@
#include "platform/assert.h"
#include "platform/globals.h"
#include "platform/utils.h"
#include "vm/constants_base.h"
@ -476,12 +477,13 @@ const VRegister kAbiFirstPreservedFpuReg = V8;
const VRegister kAbiLastPreservedFpuReg = V15;
const int kAbiPreservedFpuRegCount = 8;
const intptr_t kReservedCpuRegisters = R(SPREG) | // Dart SP
R(FPREG) | R(TMP) | R(TMP2) | R(PP) |
R(THR) | R(LR) | R(HEAP_BITS) |
R(NULL_REG) | R(R31) | // C++ SP
R(R18) | R(DISPATCH_TABLE_REG);
constexpr intptr_t kNumberOfReservedCpuRegisters = 13;
const RegList kReservedCpuRegisters = R(SPREG) | // Dart SP
R(FPREG) | R(TMP) | R(TMP2) | R(PP) |
R(THR) | R(LR) | R(HEAP_BITS) |
R(NULL_REG) | R(R31) | // C++ SP
R(R18) | R(DISPATCH_TABLE_REG);
constexpr intptr_t kNumberOfReservedCpuRegisters =
Utils::CountOneBits32(kReservedCpuRegisters);
// CPU registers available to Dart allocator.
const RegList kDartAvailableCpuRegs =
kAllCpuRegistersList & ~kReservedCpuRegisters;

View file

@ -461,18 +461,18 @@ constexpr int kAbiPreservedCpuRegCount = 11;
#if defined(DART_TARGET_OS_FUCHSIA)
// We rely on X18 not being touched by Dart generated assembly or stubs at all.
// We rely on that any calls into C++ also preserve X18.
constexpr intptr_t kReservedCpuRegisters =
constexpr RegList kReservedCpuRegisters =
R(ZR) | R(TP) | R(GP) | R(SP) | R(FP) | R(TMP) | R(TMP2) | R(PP) | R(THR) |
R(RA) | R(WRITE_BARRIER_STATE) | R(NULL_REG) | R(DISPATCH_TABLE_REG) |
R(FAR_TMP) | R(18);
constexpr intptr_t kNumberOfReservedCpuRegisters = 15;
#else
constexpr intptr_t kReservedCpuRegisters =
constexpr RegList kReservedCpuRegisters =
R(ZR) | R(TP) | R(GP) | R(SP) | R(FP) | R(TMP) | R(TMP2) | R(PP) | R(THR) |
R(RA) | R(WRITE_BARRIER_STATE) | R(NULL_REG) | R(DISPATCH_TABLE_REG) |
R(FAR_TMP);
constexpr intptr_t kNumberOfReservedCpuRegisters = 14;
#endif
constexpr intptr_t kNumberOfReservedCpuRegisters =
Utils::CountOneBits32(kReservedCpuRegisters);
// CPU registers available to Dart allocator.
constexpr RegList kDartAvailableCpuRegs =
kAllCpuRegistersList & ~kReservedCpuRegisters;

View file

@ -11,6 +11,7 @@
#include "platform/assert.h"
#include "platform/globals.h"
#include "platform/utils.h"
#include "vm/constants_base.h"
@ -412,7 +413,8 @@ const RegList kAllFpuRegistersList = 0xFFFF;
const RegList kReservedCpuRegisters =
R(SPREG) | R(FPREG) | R(TMP) | R(PP) | R(THR);
constexpr intptr_t kNumberOfReservedCpuRegisters = 5;
constexpr intptr_t kNumberOfReservedCpuRegisters =
Utils::CountOneBits32(kReservedCpuRegisters);
// CPU registers available to Dart allocator.
const RegList kDartAvailableCpuRegs =
kAllCpuRegistersList & ~kReservedCpuRegisters;