Commit 31abbcfb authored by Leszek Swirski's avatar Leszek Swirski Committed by V8 LUCI CQ

[maglev] Use RegList for free registers

Store the free registers as a RegList rather than stack of Register
values. This allows us to simplify some of the register freeing logic,
including passing the current free set to nodes for use as temporaries.

Drive-by: Replace ALWAYS_ALLOCATABLE_GENERAL_REGISTERS with
ALLOCATABLE_GENERAL_REGISTERS, which is the more general list (the former
is an implementation detail for optionally reserving a register for
the cage register).

Bug: v8:7700
Change-Id: I666e9a7547c2f4f4e578fbcbb4bd3fe3cb06dac5
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3497767Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Auto-Submit: Leszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/main@{#79344}
parent 89f02d78
...@@ -1115,7 +1115,7 @@ filegroup( ...@@ -1115,7 +1115,7 @@ filegroup(
"src/codegen/optimized-compilation-info.h", "src/codegen/optimized-compilation-info.h",
"src/codegen/pending-optimization-table.cc", "src/codegen/pending-optimization-table.cc",
"src/codegen/pending-optimization-table.h", "src/codegen/pending-optimization-table.h",
"src/codegen/register-arch.h", "src/codegen/register-base.h",
"src/codegen/register-configuration.cc", "src/codegen/register-configuration.cc",
"src/codegen/register-configuration.h", "src/codegen/register-configuration.h",
"src/codegen/register.h", "src/codegen/register.h",
......
...@@ -2728,7 +2728,7 @@ v8_header_set("v8_internal_headers") { ...@@ -2728,7 +2728,7 @@ v8_header_set("v8_internal_headers") {
"src/codegen/macro-assembler.h", "src/codegen/macro-assembler.h",
"src/codegen/optimized-compilation-info.h", "src/codegen/optimized-compilation-info.h",
"src/codegen/pending-optimization-table.h", "src/codegen/pending-optimization-table.h",
"src/codegen/register-arch.h", "src/codegen/register-base.h",
"src/codegen/register-configuration.h", "src/codegen/register-configuration.h",
"src/codegen/register.h", "src/codegen/register.h",
"src/codegen/reglist.h", "src/codegen/reglist.h",
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "src/codegen/register-arch.h" #include "src/codegen/register.h"
#if V8_TARGET_ARCH_IA32 #if V8_TARGET_ARCH_IA32
#include "src/api/api-arguments.h" #include "src/api/api-arguments.h"
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
#ifndef V8_CODEGEN_ARM_REGISTER_ARM_H_ #ifndef V8_CODEGEN_ARM_REGISTER_ARM_H_
#define V8_CODEGEN_ARM_REGISTER_ARM_H_ #define V8_CODEGEN_ARM_REGISTER_ARM_H_
#include "src/codegen/register.h" #include "src/codegen/register-base.h"
#include "src/codegen/reglist.h" #include "src/codegen/reglist.h"
namespace v8 { namespace v8 {
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
#define V8_CODEGEN_ARM64_REGISTER_ARM64_H_ #define V8_CODEGEN_ARM64_REGISTER_ARM64_H_
#include "src/codegen/arm64/utils-arm64.h" #include "src/codegen/arm64/utils-arm64.h"
#include "src/codegen/register.h" #include "src/codegen/register-base.h"
#include "src/codegen/reglist.h" #include "src/codegen/reglist.h"
#include "src/common/globals.h" #include "src/common/globals.h"
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
#ifndef V8_CODEGEN_IA32_REGISTER_IA32_H_ #ifndef V8_CODEGEN_IA32_REGISTER_IA32_H_
#define V8_CODEGEN_IA32_REGISTER_IA32_H_ #define V8_CODEGEN_IA32_REGISTER_IA32_H_
#include "src/codegen/register.h" #include "src/codegen/register-base.h"
#include "src/codegen/reglist.h" #include "src/codegen/reglist.h"
namespace v8 { namespace v8 {
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
#include "src/base/logging.h" #include "src/base/logging.h"
#include "src/codegen/interface-descriptors.h" #include "src/codegen/interface-descriptors.h"
#include "src/codegen/register-arch.h" #include "src/codegen/register.h"
#if V8_TARGET_ARCH_X64 #if V8_TARGET_ARCH_X64
#include "src/codegen/x64/interface-descriptors-x64-inl.h" #include "src/codegen/x64/interface-descriptors-x64-inl.h"
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
#include "src/base/logging.h" #include "src/base/logging.h"
#include "src/codegen/machine-type.h" #include "src/codegen/machine-type.h"
#include "src/codegen/register-arch.h" #include "src/codegen/register.h"
#include "src/codegen/tnode.h" #include "src/codegen/tnode.h"
#include "src/common/globals.h" #include "src/common/globals.h"
#include "src/execution/isolate.h" #include "src/execution/isolate.h"
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
#define V8_CODEGEN_LOONG64_REGISTER_LOONG64_H_ #define V8_CODEGEN_LOONG64_REGISTER_LOONG64_H_
#include "src/codegen/loong64/constants-loong64.h" #include "src/codegen/loong64/constants-loong64.h"
#include "src/codegen/register.h" #include "src/codegen/register-base.h"
#include "src/codegen/reglist.h" #include "src/codegen/reglist.h"
namespace v8 { namespace v8 {
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
#define V8_CODEGEN_MIPS_REGISTER_MIPS_H_ #define V8_CODEGEN_MIPS_REGISTER_MIPS_H_
#include "src/codegen/mips/constants-mips.h" #include "src/codegen/mips/constants-mips.h"
#include "src/codegen/register.h" #include "src/codegen/register-base.h"
#include "src/codegen/reglist.h" #include "src/codegen/reglist.h"
namespace v8 { namespace v8 {
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
#define V8_CODEGEN_MIPS64_REGISTER_MIPS64_H_ #define V8_CODEGEN_MIPS64_REGISTER_MIPS64_H_
#include "src/codegen/mips64/constants-mips64.h" #include "src/codegen/mips64/constants-mips64.h"
#include "src/codegen/register.h" #include "src/codegen/register-base.h"
#include "src/codegen/reglist.h" #include "src/codegen/reglist.h"
namespace v8 { namespace v8 {
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
#ifndef V8_CODEGEN_PPC_REGISTER_PPC_H_ #ifndef V8_CODEGEN_PPC_REGISTER_PPC_H_
#define V8_CODEGEN_PPC_REGISTER_PPC_H_ #define V8_CODEGEN_PPC_REGISTER_PPC_H_
#include "src/codegen/register.h" #include "src/codegen/register-base.h"
#include "src/codegen/reglist.h" #include "src/codegen/reglist.h"
namespace v8 { namespace v8 {
......
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_CODEGEN_REGISTER_ARCH_H_
#define V8_CODEGEN_REGISTER_ARCH_H_
#include "src/codegen/register.h"
#include "src/codegen/reglist.h"
#if V8_TARGET_ARCH_IA32
#include "src/codegen/ia32/register-ia32.h"
#elif V8_TARGET_ARCH_X64
#include "src/codegen/x64/register-x64.h"
#elif V8_TARGET_ARCH_ARM64
#include "src/codegen/arm64/register-arm64.h"
#elif V8_TARGET_ARCH_ARM
#include "src/codegen/arm/register-arm.h"
#elif V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_PPC64
#include "src/codegen/ppc/register-ppc.h"
#elif V8_TARGET_ARCH_MIPS
#include "src/codegen/mips/register-mips.h"
#elif V8_TARGET_ARCH_MIPS64
#include "src/codegen/mips64/register-mips64.h"
#elif V8_TARGET_ARCH_LOONG64
#include "src/codegen/loong64/register-loong64.h"
#elif V8_TARGET_ARCH_S390
#include "src/codegen/s390/register-s390.h"
#elif V8_TARGET_ARCH_RISCV64
#include "src/codegen/riscv64/register-riscv64.h"
#else
#error Unknown architecture.
#endif
namespace v8 {
namespace internal {
constexpr int AddArgumentPaddingSlots(int argument_count) {
return argument_count + ArgumentPaddingSlots(argument_count);
}
constexpr bool ShouldPadArguments(int argument_count) {
return ArgumentPaddingSlots(argument_count) != 0;
}
#ifdef DEBUG
struct CountIfValidRegisterFunctor {
template <typename RegType>
constexpr int operator()(int count, RegType reg) const {
return count + (reg.is_valid() ? 1 : 0);
}
};
template <typename RegType, typename... RegTypes,
// All arguments must be either Register or DoubleRegister.
typename = typename std::enable_if<
base::is_same<Register, RegType, RegTypes...>::value ||
base::is_same<DoubleRegister, RegType, RegTypes...>::value>::type>
inline constexpr bool AreAliased(RegType first_reg, RegTypes... regs) {
int num_different_regs = NumRegs(RegType::ListOf(first_reg, regs...));
int num_given_regs =
base::fold(CountIfValidRegisterFunctor{}, 0, first_reg, regs...);
return num_different_regs < num_given_regs;
}
#endif
} // namespace internal
} // namespace v8
#endif // V8_CODEGEN_REGISTER_ARCH_H_
// Copyright 2012 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_CODEGEN_REGISTER_BASE_H_
#define V8_CODEGEN_REGISTER_BASE_H_
#include "src/base/bits.h"
#include "src/base/bounds.h"
#include "src/codegen/reglist.h"
namespace v8 {
namespace internal {
// Base type for CPU Registers.
//
// 1) We would prefer to use an enum for registers, but enum values are
// assignment-compatible with int, which has caused code-generation bugs.
//
// 2) By not using an enum, we are possibly preventing the compiler from
// doing certain constant folds, which may significantly reduce the
// code generated for some assembly instructions (because they boil down
// to a few constants). If this is a problem, we could change the code
// such that we use an enum in optimized mode, and the class in debug
// mode. This way we get the compile-time error checking in debug mode
// and best performance in optimized code.
template <typename SubType, int kAfterLastRegister>
class RegisterBase {
public:
static constexpr int kCode_no_reg = -1;
static constexpr int kNumRegisters = kAfterLastRegister;
static constexpr SubType no_reg() { return SubType{kCode_no_reg}; }
static constexpr SubType from_code(int code) {
DCHECK(base::IsInRange(code, 0, kNumRegisters - 1));
return SubType{code};
}
template <typename... Register>
static constexpr RegList ListOf(Register... regs) {
return CombineRegLists(regs.bit()...);
}
constexpr bool is_valid() const { return reg_code_ != kCode_no_reg; }
constexpr int code() const {
DCHECK(is_valid());
return reg_code_;
}
constexpr RegList bit() const {
return is_valid() ? RegList{1} << code() : RegList{};
}
static constexpr SubType AnyOf(RegList list) {
DCHECK_NE(kEmptyRegList, list);
return from_code(base::bits::CountTrailingZeros(list));
}
static constexpr SubType TakeAny(RegList* list) {
RegList value = *list;
SubType result = AnyOf(value);
result.RemoveFrom(list);
return result;
}
constexpr void InsertInto(RegList* list) const {
DCHECK_NE(bit(), (*list) & bit());
*list |= bit();
}
constexpr void RemoveFrom(RegList* list) const {
DCHECK_EQ(bit(), (*list) & bit());
*list ^= bit();
}
inline constexpr bool operator==(SubType other) const {
return reg_code_ == other.reg_code_;
}
inline constexpr bool operator!=(SubType other) const {
return reg_code_ != other.reg_code_;
}
// Used to print the name of some special registers.
static const char* GetSpecialRegisterName(int code) { return "UNKNOWN"; }
protected:
explicit constexpr RegisterBase(int code) : reg_code_(code) {}
private:
int reg_code_;
};
template <typename RegType,
typename = decltype(RegisterName(std::declval<RegType>()))>
inline std::ostream& operator<<(std::ostream& os, RegType reg) {
return os << RegisterName(reg);
}
// Helper macros to define a {RegisterName} method based on a macro list
// containing all names.
#define DEFINE_REGISTER_NAMES_NAME(name) #name,
#define DEFINE_REGISTER_NAMES(RegType, LIST) \
inline const char* RegisterName(RegType reg) { \
static constexpr const char* Names[] = {LIST(DEFINE_REGISTER_NAMES_NAME)}; \
STATIC_ASSERT(arraysize(Names) == RegType::kNumRegisters); \
return reg.is_valid() ? Names[reg.code()] : "invalid"; \
}
} // namespace internal
} // namespace v8
#endif // V8_CODEGEN_REGISTER_BASE_H_
...@@ -3,9 +3,10 @@ ...@@ -3,9 +3,10 @@
// found in the LICENSE file. // found in the LICENSE file.
#include "src/codegen/register-configuration.h" #include "src/codegen/register-configuration.h"
#include "src/base/lazy-instance.h" #include "src/base/lazy-instance.h"
#include "src/codegen/cpu-features.h" #include "src/codegen/cpu-features.h"
#include "src/codegen/register-arch.h" #include "src/codegen/register.h"
#include "src/common/globals.h" #include "src/common/globals.h"
namespace v8 { namespace v8 {
......
// Copyright 2012 the V8 project authors. All rights reserved. // Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef V8_CODEGEN_REGISTER_H_ #ifndef V8_CODEGEN_REGISTER_H_
#define V8_CODEGEN_REGISTER_H_ #define V8_CODEGEN_REGISTER_H_
#include "src/base/bits.h" #include "src/codegen/register-base.h"
#include "src/base/bounds.h"
#include "src/codegen/reglist.h" #include "src/codegen/reglist.h"
namespace v8 { #if V8_TARGET_ARCH_IA32
#include "src/codegen/ia32/register-ia32.h"
#elif V8_TARGET_ARCH_X64
#include "src/codegen/x64/register-x64.h"
#elif V8_TARGET_ARCH_ARM64
#include "src/codegen/arm64/register-arm64.h"
#elif V8_TARGET_ARCH_ARM
#include "src/codegen/arm/register-arm.h"
#elif V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_PPC64
#include "src/codegen/ppc/register-ppc.h"
#elif V8_TARGET_ARCH_MIPS
#include "src/codegen/mips/register-mips.h"
#elif V8_TARGET_ARCH_MIPS64
#include "src/codegen/mips64/register-mips64.h"
#elif V8_TARGET_ARCH_LOONG64
#include "src/codegen/loong64/register-loong64.h"
#elif V8_TARGET_ARCH_S390
#include "src/codegen/s390/register-s390.h"
#elif V8_TARGET_ARCH_RISCV64
#include "src/codegen/riscv64/register-riscv64.h"
#else
#error Unknown architecture.
#endif
namespace v8 {
namespace internal { namespace internal {
// Base type for CPU Registers. #define LIST_REG(V) V,
// static constexpr RegList kAllocatableGeneralRegisters = Register::ListOf(
// 1) We would prefer to use an enum for registers, but enum values are ALLOCATABLE_GENERAL_REGISTERS(LIST_REG) Register::no_reg());
// assignment-compatible with int, which has caused code-generation bugs. #undef LIST_REG
//
// 2) By not using an enum, we are possibly preventing the compiler from
// doing certain constant folds, which may significantly reduce the
// code generated for some assembly instructions (because they boil down
// to a few constants). If this is a problem, we could change the code
// such that we use an enum in optimized mode, and the class in debug
// mode. This way we get the compile-time error checking in debug mode
// and best performance in optimized code.
template <typename SubType, int kAfterLastRegister>
class RegisterBase {
public:
static constexpr int kCode_no_reg = -1;
static constexpr int kNumRegisters = kAfterLastRegister;
static constexpr SubType no_reg() { return SubType{kCode_no_reg}; }
static constexpr SubType from_code(int code) {
DCHECK(base::IsInRange(code, 0, kNumRegisters - 1));
return SubType{code};
}
template <typename... Register>
static constexpr RegList ListOf(Register... regs) {
return CombineRegLists(regs.bit()...);
}
constexpr bool is_valid() const { return reg_code_ != kCode_no_reg; } constexpr int AddArgumentPaddingSlots(int argument_count) {
return argument_count + ArgumentPaddingSlots(argument_count);
constexpr int code() const { }
DCHECK(is_valid());
return reg_code_;
}
constexpr RegList bit() const {
return is_valid() ? RegList{1} << code() : RegList{};
}
static constexpr SubType AnyOf(RegList list) {
DCHECK_NE(kEmptyRegList, list);
return from_code(base::bits::CountTrailingZeros(list));
}
static constexpr SubType TakeAny(RegList* list) {
RegList value = *list;
SubType result = AnyOf(value);
result.RemoveFrom(list);
return result;
}
constexpr void RemoveFrom(RegList* list) const { constexpr bool ShouldPadArguments(int argument_count) {
DCHECK_EQ(bit(), (*list) & bit()); return ArgumentPaddingSlots(argument_count) != 0;
*list ^= bit(); }
}
inline constexpr bool operator==(SubType other) const { #ifdef DEBUG
return reg_code_ == other.reg_code_; struct CountIfValidRegisterFunctor {
} template <typename RegType>
inline constexpr bool operator!=(SubType other) const { constexpr int operator()(int count, RegType reg) const {
return reg_code_ != other.reg_code_; return count + (reg.is_valid() ? 1 : 0);
} }
// Used to print the name of some special registers.
static const char* GetSpecialRegisterName(int code) { return "UNKNOWN"; }
protected:
explicit constexpr RegisterBase(int code) : reg_code_(code) {}
private:
int reg_code_;
}; };
template <typename RegType, template <typename RegType, typename... RegTypes,
typename = decltype(RegisterName(std::declval<RegType>()))> // All arguments must be either Register or DoubleRegister.
inline std::ostream& operator<<(std::ostream& os, RegType reg) { typename = typename std::enable_if<
return os << RegisterName(reg); base::is_same<Register, RegType, RegTypes...>::value ||
base::is_same<DoubleRegister, RegType, RegTypes...>::value>::type>
inline constexpr bool AreAliased(RegType first_reg, RegTypes... regs) {
int num_different_regs = NumRegs(RegType::ListOf(first_reg, regs...));
int num_given_regs =
base::fold(CountIfValidRegisterFunctor{}, 0, first_reg, regs...);
return num_different_regs < num_given_regs;
} }
#endif
// Helper macros to define a {RegisterName} method based on a macro list
// containing all names.
#define DEFINE_REGISTER_NAMES_NAME(name) #name,
#define DEFINE_REGISTER_NAMES(RegType, LIST) \
inline const char* RegisterName(RegType reg) { \
static constexpr const char* Names[] = {LIST(DEFINE_REGISTER_NAMES_NAME)}; \
STATIC_ASSERT(arraysize(Names) == RegType::kNumRegisters); \
return reg.is_valid() ? Names[reg.code()] : "invalid"; \
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
#endif // V8_CODEGEN_REGISTER_H_ #endif // V8_CODEGEN_REGISTER_H_
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
#ifndef V8_CODEGEN_RISCV64_REGISTER_RISCV64_H_ #ifndef V8_CODEGEN_RISCV64_REGISTER_RISCV64_H_
#define V8_CODEGEN_RISCV64_REGISTER_RISCV64_H_ #define V8_CODEGEN_RISCV64_REGISTER_RISCV64_H_
#include "src/codegen/register.h" #include "src/codegen/register-base.h"
#include "src/codegen/reglist.h" #include "src/codegen/reglist.h"
#include "src/codegen/riscv64/constants-riscv64.h" #include "src/codegen/riscv64/constants-riscv64.h"
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
#ifndef V8_CODEGEN_S390_REGISTER_S390_H_ #ifndef V8_CODEGEN_S390_REGISTER_S390_H_
#define V8_CODEGEN_S390_REGISTER_S390_H_ #define V8_CODEGEN_S390_REGISTER_S390_H_
#include "src/codegen/register.h" #include "src/codegen/register-base.h"
#include "src/codegen/reglist.h" #include "src/codegen/reglist.h"
namespace v8 { namespace v8 {
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
#include "src/codegen/assembler.h" #include "src/codegen/assembler.h"
#include "src/codegen/cpu-features.h" #include "src/codegen/cpu-features.h"
#include "src/codegen/register-arch.h" #include "src/codegen/register.h"
#if V8_TARGET_ARCH_IA32 #if V8_TARGET_ARCH_IA32
#include "src/codegen/ia32/register-ia32.h" #include "src/codegen/ia32/register-ia32.h"
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
#ifndef V8_CODEGEN_X64_REGISTER_X64_H_ #ifndef V8_CODEGEN_X64_REGISTER_X64_H_
#define V8_CODEGEN_X64_REGISTER_X64_H_ #define V8_CODEGEN_X64_REGISTER_X64_H_
#include "src/codegen/register.h" #include "src/codegen/register-base.h"
#include "src/codegen/reglist.h" #include "src/codegen/reglist.h"
namespace v8 { namespace v8 {
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
#include "src/base/compiler-specific.h" #include "src/base/compiler-specific.h"
#include "src/base/numbers/double.h" #include "src/base/numbers/double.h"
#include "src/codegen/external-reference.h" #include "src/codegen/external-reference.h"
#include "src/codegen/register-arch.h" #include "src/codegen/register.h"
#include "src/codegen/source-position.h" #include "src/codegen/source-position.h"
#include "src/common/globals.h" #include "src/common/globals.h"
#include "src/compiler/backend/instruction-codes.h" #include "src/compiler/backend/instruction-codes.h"
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
#include "src/base/flags.h" #include "src/base/flags.h"
#include "src/codegen/interface-descriptors.h" #include "src/codegen/interface-descriptors.h"
#include "src/codegen/machine-type.h" #include "src/codegen/machine-type.h"
#include "src/codegen/register-arch.h" #include "src/codegen/register.h"
#include "src/codegen/reglist.h" #include "src/codegen/reglist.h"
#include "src/codegen/signature.h" #include "src/codegen/signature.h"
#include "src/common/globals.h" #include "src/common/globals.h"
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
#ifndef V8_DEOPTIMIZER_FRAME_DESCRIPTION_H_ #ifndef V8_DEOPTIMIZER_FRAME_DESCRIPTION_H_
#define V8_DEOPTIMIZER_FRAME_DESCRIPTION_H_ #define V8_DEOPTIMIZER_FRAME_DESCRIPTION_H_
#include "src/codegen/register-arch.h" #include "src/codegen/register.h"
#include "src/execution/frame-constants.h" #include "src/execution/frame-constants.h"
#include "src/utils/boxed-float.h" #include "src/utils/boxed-float.h"
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
#ifndef V8_DEOPTIMIZER_TRANSLATION_ARRAY_H_ #ifndef V8_DEOPTIMIZER_TRANSLATION_ARRAY_H_
#define V8_DEOPTIMIZER_TRANSLATION_ARRAY_H_ #define V8_DEOPTIMIZER_TRANSLATION_ARRAY_H_
#include "src/codegen/register-arch.h" #include "src/codegen/register.h"
#include "src/deoptimizer/translation-opcode.h" #include "src/deoptimizer/translation-opcode.h"
#include "src/objects/fixed-array.h" #include "src/objects/fixed-array.h"
#include "src/zone/zone-containers.h" #include "src/zone/zone-containers.h"
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
#include "src/base/compiler-specific.h" #include "src/base/compiler-specific.h"
#include "src/base/memory.h" #include "src/base/memory.h"
#include "src/codegen/register-arch.h" #include "src/codegen/register.h"
#include "src/common/globals.h" #include "src/common/globals.h"
#include "src/zone/zone-containers.h" #include "src/zone/zone-containers.h"
......
...@@ -340,7 +340,7 @@ class MergePointInterpreterFrameState { ...@@ -340,7 +340,7 @@ class MergePointInterpreterFrameState {
#define N(V) RegisterState{nullptr}, #define N(V) RegisterState{nullptr},
RegisterState register_values_[kAllocatableGeneralRegisterCount] = { RegisterState register_values_[kAllocatableGeneralRegisterCount] = {
ALWAYS_ALLOCATABLE_GENERAL_REGISTERS(N)}; ALLOCATABLE_GENERAL_REGISTERS(N)};
#undef N #undef N
}; };
......
...@@ -499,7 +499,6 @@ void CheckMaps::GenerateCode(MaglevCodeGenState* code_gen_state, ...@@ -499,7 +499,6 @@ void CheckMaps::GenerateCode(MaglevCodeGenState* code_gen_state,
Register object = ToRegister(actual_map_input()); Register object = ToRegister(actual_map_input());
RegList temps = temporaries(); RegList temps = temporaries();
Register map_tmp = Register::TakeAny(&temps); Register map_tmp = Register::TakeAny(&temps);
DCHECK_EQ(kEmptyRegList, temps);
__ LoadMap(map_tmp, object); __ LoadMap(map_tmp, object);
__ Cmp(map_tmp, map().object()); __ Cmp(map_tmp, map().object());
......
...@@ -17,7 +17,7 @@ class ValueNode; ...@@ -17,7 +17,7 @@ class ValueNode;
#define COUNT(V) +1 #define COUNT(V) +1
static constexpr int kAllocatableGeneralRegisterCount = static constexpr int kAllocatableGeneralRegisterCount =
ALWAYS_ALLOCATABLE_GENERAL_REGISTERS(COUNT); ALLOCATABLE_GENERAL_REGISTERS(COUNT);
#undef COUNT #undef COUNT
constexpr uint8_t MapRegisterToIndex(Register r) { constexpr uint8_t MapRegisterToIndex(Register r) {
...@@ -25,7 +25,7 @@ constexpr uint8_t MapRegisterToIndex(Register r) { ...@@ -25,7 +25,7 @@ constexpr uint8_t MapRegisterToIndex(Register r) {
#define EMIT_BRANCH(V) \ #define EMIT_BRANCH(V) \
if (r == V) return count; \ if (r == V) return count; \
count++; count++;
ALWAYS_ALLOCATABLE_GENERAL_REGISTERS(EMIT_BRANCH) ALLOCATABLE_GENERAL_REGISTERS(EMIT_BRANCH)
#undef EMIT_BRANCH #undef EMIT_BRANCH
// TODO(v8:7700): Re-enable UNREACHABLE once we figure out how to to avoid // TODO(v8:7700): Re-enable UNREACHABLE once we figure out how to to avoid
// the gcc error 'call to non-constexpr function'. // the gcc error 'call to non-constexpr function'.
...@@ -38,7 +38,7 @@ constexpr Register MapIndexToRegister(int i) { ...@@ -38,7 +38,7 @@ constexpr Register MapIndexToRegister(int i) {
#define EMIT_BRANCH(V) \ #define EMIT_BRANCH(V) \
if (i == count) return V; \ if (i == count) return V; \
count++; count++;
ALWAYS_ALLOCATABLE_GENERAL_REGISTERS(EMIT_BRANCH) ALLOCATABLE_GENERAL_REGISTERS(EMIT_BRANCH)
#undef EMIT_BRANCH #undef EMIT_BRANCH
// TODO(v8:7700): Re-enable UNREACHABLE once we figure out how to to avoid // TODO(v8:7700): Re-enable UNREACHABLE once we figure out how to to avoid
// the gcc error 'call to non-constexpr function'. // the gcc error 'call to non-constexpr function'.
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "src/maglev/maglev-regalloc.h" #include "src/maglev/maglev-regalloc.h"
#include "src/base/bits.h"
#include "src/base/logging.h" #include "src/base/logging.h"
#include "src/codegen/reglist.h" #include "src/codegen/reglist.h"
#include "src/compiler/backend/instruction.h" #include "src/compiler/backend/instruction.h"
...@@ -81,9 +82,6 @@ StraightForwardRegisterAllocator::StraightForwardRegisterAllocator( ...@@ -81,9 +82,6 @@ StraightForwardRegisterAllocator::StraightForwardRegisterAllocator(
MaglevCompilationUnit* compilation_unit, Graph* graph) MaglevCompilationUnit* compilation_unit, Graph* graph)
: compilation_unit_(compilation_unit) { : compilation_unit_(compilation_unit) {
ComputePostDominatingHoles(graph); ComputePostDominatingHoles(graph);
for (int i = 0; i < kAllocatableGeneralRegisterCount; i++) {
free_registers_[i] = i;
}
AllocateRegisters(graph); AllocateRegisters(graph);
graph->set_stack_slots(top_of_stack_); graph->set_stack_slots(top_of_stack_);
} }
...@@ -431,9 +429,8 @@ void StraightForwardRegisterAllocator::Free(const Register& reg) { ...@@ -431,9 +429,8 @@ void StraightForwardRegisterAllocator::Free(const Register& reg) {
if (node->is_spilled()) return; if (node->is_spilled()) return;
// Try to move the value to another register. // Try to move the value to another register.
if (free_register_size_ > 0) { if (free_registers_ != kEmptyRegList) {
Register target_reg = Register target_reg = Register::TakeAny(&free_registers_);
MapIndexToRegister(free_registers_[--free_register_size_]);
SetRegister(target_reg, node); SetRegister(target_reg, node);
// Emit a gapmove. // Emit a gapmove.
compiler::AllocatedOperand source(compiler::LocationOperand::REGISTER, compiler::AllocatedOperand source(compiler::LocationOperand::REGISTER,
...@@ -626,7 +623,7 @@ void StraightForwardRegisterAllocator::SpillRegisters() { ...@@ -626,7 +623,7 @@ void StraightForwardRegisterAllocator::SpillRegisters() {
void StraightForwardRegisterAllocator::FreeRegister(int i) { void StraightForwardRegisterAllocator::FreeRegister(int i) {
register_values_[i] = nullptr; register_values_[i] = nullptr;
free_registers_[free_register_size_++] = i; MapIndexToRegister(i).InsertInto(&free_registers_);
} }
void StraightForwardRegisterAllocator::SpillAndClearRegisters() { void StraightForwardRegisterAllocator::SpillAndClearRegisters() {
...@@ -668,7 +665,7 @@ void StraightForwardRegisterAllocator::FreeSomeRegister() { ...@@ -668,7 +665,7 @@ void StraightForwardRegisterAllocator::FreeSomeRegister() {
compiler::AllocatedOperand StraightForwardRegisterAllocator::AllocateRegister( compiler::AllocatedOperand StraightForwardRegisterAllocator::AllocateRegister(
ValueNode* node) { ValueNode* node) {
if (free_register_size_ == 0) FreeSomeRegister(); if (free_registers_ == kEmptyRegList) FreeSomeRegister();
compiler::InstructionOperand allocation = TryAllocateRegister(node); compiler::InstructionOperand allocation = TryAllocateRegister(node);
DCHECK(allocation.IsAllocated()); DCHECK(allocation.IsAllocated());
return compiler::AllocatedOperand::cast(allocation); return compiler::AllocatedOperand::cast(allocation);
...@@ -678,13 +675,7 @@ compiler::AllocatedOperand StraightForwardRegisterAllocator::ForceAllocate( ...@@ -678,13 +675,7 @@ compiler::AllocatedOperand StraightForwardRegisterAllocator::ForceAllocate(
const Register& reg, ValueNode* node) { const Register& reg, ValueNode* node) {
if (register_values_[MapRegisterToIndex(reg)] == nullptr) { if (register_values_[MapRegisterToIndex(reg)] == nullptr) {
// If it's already free, remove it from the free list. // If it's already free, remove it from the free list.
// TODO(verwaest): This should just be a mask. reg.RemoveFrom(&free_registers_);
for (int i = 0; i < free_register_size_; i++) {
if (MapRegisterToIndex(reg) == free_registers_[i]) {
std::swap(free_registers_[i], free_registers_[--free_register_size_]);
break;
}
}
} else if (register_values_[MapRegisterToIndex(reg)] == node) { } else if (register_values_[MapRegisterToIndex(reg)] == node) {
return compiler::AllocatedOperand(compiler::LocationOperand::REGISTER, return compiler::AllocatedOperand(compiler::LocationOperand::REGISTER,
MachineRepresentation::kTagged, MachineRepresentation::kTagged,
...@@ -694,9 +685,8 @@ compiler::AllocatedOperand StraightForwardRegisterAllocator::ForceAllocate( ...@@ -694,9 +685,8 @@ compiler::AllocatedOperand StraightForwardRegisterAllocator::ForceAllocate(
DCHECK_NULL(register_values_[MapRegisterToIndex(reg)]); DCHECK_NULL(register_values_[MapRegisterToIndex(reg)]);
} }
#ifdef DEBUG #ifdef DEBUG
for (int i = 0; i < free_register_size_; i++) { DCHECK_NE(free_registers_,
CHECK_NE(MapRegisterToIndex(reg), free_registers_[i]); CombineRegLists(free_registers_, Register::ListOf(reg)));
}
#endif #endif
SetRegister(reg, node); SetRegister(reg, node);
return compiler::AllocatedOperand(compiler::LocationOperand::REGISTER, return compiler::AllocatedOperand(compiler::LocationOperand::REGISTER,
...@@ -714,29 +704,28 @@ void StraightForwardRegisterAllocator::SetRegister(Register reg, ...@@ -714,29 +704,28 @@ void StraightForwardRegisterAllocator::SetRegister(Register reg,
compiler::InstructionOperand compiler::InstructionOperand
StraightForwardRegisterAllocator::TryAllocateRegister(ValueNode* node) { StraightForwardRegisterAllocator::TryAllocateRegister(ValueNode* node) {
if (free_register_size_ == 0) return compiler::InstructionOperand(); if (free_registers_ == kEmptyRegList) return compiler::InstructionOperand();
int index = free_registers_[--free_register_size_]; Register reg = Register::TakeAny(&free_registers_);
// Allocation succeeded. This might have found an existing allocation. // Allocation succeeded. This might have found an existing allocation.
// Simply update the state anyway. // Simply update the state anyway.
SetRegister(MapIndexToRegister(index), node); SetRegister(reg, node);
return compiler::AllocatedOperand(compiler::LocationOperand::REGISTER, return compiler::AllocatedOperand(compiler::LocationOperand::REGISTER,
MachineRepresentation::kTagged, MachineRepresentation::kTagged, reg.code());
MapIndexToRegister(index).code());
} }
void StraightForwardRegisterAllocator::AssignTemporaries(NodeBase* node) { void StraightForwardRegisterAllocator::AssignTemporaries(NodeBase* node) {
int num_temporaries_needed = node->num_temporaries_needed(); int num_temporaries_needed = node->num_temporaries_needed();
int num_free_registers = base::bits::CountPopulation(free_registers_);
RegList free_registers = kEmptyRegList; // Free extra registers if necessary.
while (num_temporaries_needed > free_register_size_) FreeSomeRegister(); for (int i = num_free_registers; i < num_temporaries_needed; ++i) {
FreeSomeRegister();
for (int i = 0; i < node->num_temporaries_needed(); i++) {
Register reg = MapIndexToRegister(free_registers_[i]);
free_registers = CombineRegLists(free_registers, Register::ListOf(reg));
} }
node->assign_temporaries(free_registers); DCHECK_GE(base::bits::CountPopulation(free_registers_),
num_temporaries_needed);
node->assign_temporaries(free_registers_);
} }
void StraightForwardRegisterAllocator::InitializeRegisterValues( void StraightForwardRegisterAllocator::InitializeRegisterValues(
...@@ -751,7 +740,7 @@ void StraightForwardRegisterAllocator::InitializeRegisterValues( ...@@ -751,7 +740,7 @@ void StraightForwardRegisterAllocator::InitializeRegisterValues(
} }
// Mark no register as free. // Mark no register as free.
free_register_size_ = 0; free_registers_ = kEmptyRegList;
// Then fill it in with target information. // Then fill it in with target information.
for (int i = 0; i < kAllocatableGeneralRegisterCount; i++) { for (int i = 0; i < kAllocatableGeneralRegisterCount; i++) {
......
...@@ -31,13 +31,11 @@ class StraightForwardRegisterAllocator { ...@@ -31,13 +31,11 @@ class StraightForwardRegisterAllocator {
#define N(V) nullptr, #define N(V) nullptr,
ValueNode* register_values_[kAllocatableGeneralRegisterCount] = { ValueNode* register_values_[kAllocatableGeneralRegisterCount] = {
ALWAYS_ALLOCATABLE_GENERAL_REGISTERS(N)}; ALLOCATABLE_GENERAL_REGISTERS(N)};
#undef N #undef N
int top_of_stack_ = 0; int top_of_stack_ = 0;
// TODO(verwaest): Make this a RegList. RegList free_registers_ = kAllocatableGeneralRegisters;
uint8_t free_register_size_ = kAllocatableGeneralRegisterCount;
uint8_t free_registers_[kAllocatableGeneralRegisterCount];
std::vector<uint32_t> free_slots_; std::vector<uint32_t> free_slots_;
void ComputePostDominatingHoles(Graph* graph); void ComputePostDominatingHoles(Graph* graph);
......
...@@ -337,7 +337,7 @@ header = ''' ...@@ -337,7 +337,7 @@ header = '''
*/ */
#include "src/init/v8.h" #include "src/init/v8.h"
#include "src/codegen/register-arch.h" #include "src/codegen/register.h"
#include "src/execution/frames.h" #include "src/execution/frames.h"
#include "src/execution/frames-inl.h" /* for architecture-specific frame constants */ #include "src/execution/frames-inl.h" /* for architecture-specific frame constants */
#include "src/objects/contexts.h" #include "src/objects/contexts.h"
...@@ -359,7 +359,7 @@ STACK_FRAME_TYPE_LIST(FRAME_CONST) ...@@ -359,7 +359,7 @@ STACK_FRAME_TYPE_LIST(FRAME_CONST)
#undef FRAME_CONST #undef FRAME_CONST
''' % sys.argv[0]; ''' % sys.argv[0]
footer = ''' footer = '''
} }
...@@ -440,12 +440,12 @@ def load_objects_from_file(objfilename, checktypes): ...@@ -440,12 +440,12 @@ def load_objects_from_file(objfilename, checktypes):
continue; continue;
if (in_torque_insttype and (not line or line.isspace())): if (in_torque_insttype and (not line or line.isspace())):
in_torque_insttype = False in_torque_insttype = False
continue continue
if (in_torque_fulldef and (not line or line.isspace())): if (in_torque_fulldef and (not line or line.isspace())):
in_torque_fulldef = False in_torque_fulldef = False
continue continue
pre = line.strip() pre = line.strip()
line = re.sub('// .*', '', line.strip()); line = re.sub('// .*', '', line.strip());
...@@ -497,7 +497,7 @@ def load_objects_from_file(objfilename, checktypes): ...@@ -497,7 +497,7 @@ def load_objects_from_file(objfilename, checktypes):
for entry in entries: for entry in entries:
entry = entry.strip() entry = entry.strip()
if not entry: if not entry:
continue continue
start = entry.find('('); start = entry.find('(');
end = entry.find(')', start); end = entry.find(')', start);
rest = entry[start + 1: end]; rest = entry[start + 1: end];
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment