[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/+/3497767 Reviewed-by: Jakob 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}
This commit is contained in:
parent
89f02d7808
commit
31abbcfb4d
@ -1115,7 +1115,7 @@ filegroup(
|
||||
"src/codegen/optimized-compilation-info.h",
|
||||
"src/codegen/pending-optimization-table.cc",
|
||||
"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.h",
|
||||
"src/codegen/register.h",
|
||||
|
2
BUILD.gn
2
BUILD.gn
@ -2728,7 +2728,7 @@ v8_header_set("v8_internal_headers") {
|
||||
"src/codegen/macro-assembler.h",
|
||||
"src/codegen/optimized-compilation-info.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.h",
|
||||
"src/codegen/reglist.h",
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "src/codegen/register-arch.h"
|
||||
#include "src/codegen/register.h"
|
||||
#if V8_TARGET_ARCH_IA32
|
||||
|
||||
#include "src/api/api-arguments.h"
|
||||
|
@ -5,7 +5,7 @@
|
||||
#ifndef 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"
|
||||
|
||||
namespace v8 {
|
||||
|
@ -6,7 +6,7 @@
|
||||
#define V8_CODEGEN_ARM64_REGISTER_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/common/globals.h"
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
#ifndef 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"
|
||||
|
||||
namespace v8 {
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
#include "src/base/logging.h"
|
||||
#include "src/codegen/interface-descriptors.h"
|
||||
#include "src/codegen/register-arch.h"
|
||||
#include "src/codegen/register.h"
|
||||
|
||||
#if V8_TARGET_ARCH_X64
|
||||
#include "src/codegen/x64/interface-descriptors-x64-inl.h"
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
#include "src/base/logging.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/common/globals.h"
|
||||
#include "src/execution/isolate.h"
|
||||
|
@ -6,7 +6,7 @@
|
||||
#define V8_CODEGEN_LOONG64_REGISTER_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"
|
||||
|
||||
namespace v8 {
|
||||
|
@ -6,7 +6,7 @@
|
||||
#define V8_CODEGEN_MIPS_REGISTER_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"
|
||||
|
||||
namespace v8 {
|
||||
|
@ -6,7 +6,7 @@
|
||||
#define V8_CODEGEN_MIPS64_REGISTER_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"
|
||||
|
||||
namespace v8 {
|
||||
|
@ -5,7 +5,7 @@
|
||||
#ifndef 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"
|
||||
|
||||
namespace v8 {
|
||||
|
@ -1,70 +0,0 @@
|
||||
// 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_
|
115
src/codegen/register-base.h
Normal file
115
src/codegen/register-base.h
Normal file
@ -0,0 +1,115 @@
|
||||
// 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 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "src/codegen/register-configuration.h"
|
||||
|
||||
#include "src/base/lazy-instance.h"
|
||||
#include "src/codegen/cpu-features.h"
|
||||
#include "src/codegen/register-arch.h"
|
||||
#include "src/codegen/register.h"
|
||||
#include "src/common/globals.h"
|
||||
|
||||
namespace v8 {
|
||||
|
@ -1,109 +1,75 @@
|
||||
// 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
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_CODEGEN_REGISTER_H_
|
||||
#define V8_CODEGEN_REGISTER_H_
|
||||
|
||||
#include "src/base/bits.h"
|
||||
#include "src/base/bounds.h"
|
||||
#include "src/codegen/register-base.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 {
|
||||
|
||||
// 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;
|
||||
#define LIST_REG(V) V,
|
||||
static constexpr RegList kAllocatableGeneralRegisters = Register::ListOf(
|
||||
ALLOCATABLE_GENERAL_REGISTERS(LIST_REG) Register::no_reg());
|
||||
#undef LIST_REG
|
||||
|
||||
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 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);
|
||||
constexpr int AddArgumentPaddingSlots(int argument_count) {
|
||||
return argument_count + ArgumentPaddingSlots(argument_count);
|
||||
}
|
||||
|
||||
// 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"; \
|
||||
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_H_
|
||||
|
@ -5,7 +5,7 @@
|
||||
#ifndef 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/riscv64/constants-riscv64.h"
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
#ifndef 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"
|
||||
|
||||
namespace v8 {
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
#include "src/codegen/assembler.h"
|
||||
#include "src/codegen/cpu-features.h"
|
||||
#include "src/codegen/register-arch.h"
|
||||
#include "src/codegen/register.h"
|
||||
|
||||
#if V8_TARGET_ARCH_IA32
|
||||
#include "src/codegen/ia32/register-ia32.h"
|
||||
|
@ -5,7 +5,7 @@
|
||||
#ifndef 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"
|
||||
|
||||
namespace v8 {
|
||||
|
@ -11,7 +11,7 @@
|
||||
#include "src/base/compiler-specific.h"
|
||||
#include "src/base/numbers/double.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/common/globals.h"
|
||||
#include "src/compiler/backend/instruction-codes.h"
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include "src/base/flags.h"
|
||||
#include "src/codegen/interface-descriptors.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/signature.h"
|
||||
#include "src/common/globals.h"
|
||||
|
@ -5,7 +5,7 @@
|
||||
#ifndef 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/utils/boxed-float.h"
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
#ifndef 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/objects/fixed-array.h"
|
||||
#include "src/zone/zone-containers.h"
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
#include "src/base/compiler-specific.h"
|
||||
#include "src/base/memory.h"
|
||||
#include "src/codegen/register-arch.h"
|
||||
#include "src/codegen/register.h"
|
||||
#include "src/common/globals.h"
|
||||
#include "src/zone/zone-containers.h"
|
||||
|
||||
|
@ -340,7 +340,7 @@ class MergePointInterpreterFrameState {
|
||||
|
||||
#define N(V) RegisterState{nullptr},
|
||||
RegisterState register_values_[kAllocatableGeneralRegisterCount] = {
|
||||
ALWAYS_ALLOCATABLE_GENERAL_REGISTERS(N)};
|
||||
ALLOCATABLE_GENERAL_REGISTERS(N)};
|
||||
#undef N
|
||||
};
|
||||
|
||||
|
@ -499,7 +499,6 @@ void CheckMaps::GenerateCode(MaglevCodeGenState* code_gen_state,
|
||||
Register object = ToRegister(actual_map_input());
|
||||
RegList temps = temporaries();
|
||||
Register map_tmp = Register::TakeAny(&temps);
|
||||
DCHECK_EQ(kEmptyRegList, temps);
|
||||
|
||||
__ LoadMap(map_tmp, object);
|
||||
__ Cmp(map_tmp, map().object());
|
||||
|
@ -17,7 +17,7 @@ class ValueNode;
|
||||
|
||||
#define COUNT(V) +1
|
||||
static constexpr int kAllocatableGeneralRegisterCount =
|
||||
ALWAYS_ALLOCATABLE_GENERAL_REGISTERS(COUNT);
|
||||
ALLOCATABLE_GENERAL_REGISTERS(COUNT);
|
||||
#undef COUNT
|
||||
|
||||
constexpr uint8_t MapRegisterToIndex(Register r) {
|
||||
@ -25,7 +25,7 @@ constexpr uint8_t MapRegisterToIndex(Register r) {
|
||||
#define EMIT_BRANCH(V) \
|
||||
if (r == V) return count; \
|
||||
count++;
|
||||
ALWAYS_ALLOCATABLE_GENERAL_REGISTERS(EMIT_BRANCH)
|
||||
ALLOCATABLE_GENERAL_REGISTERS(EMIT_BRANCH)
|
||||
#undef EMIT_BRANCH
|
||||
// TODO(v8:7700): Re-enable UNREACHABLE once we figure out how to to avoid
|
||||
// the gcc error 'call to non-constexpr function'.
|
||||
@ -38,7 +38,7 @@ constexpr Register MapIndexToRegister(int i) {
|
||||
#define EMIT_BRANCH(V) \
|
||||
if (i == count) return V; \
|
||||
count++;
|
||||
ALWAYS_ALLOCATABLE_GENERAL_REGISTERS(EMIT_BRANCH)
|
||||
ALLOCATABLE_GENERAL_REGISTERS(EMIT_BRANCH)
|
||||
#undef EMIT_BRANCH
|
||||
// TODO(v8:7700): Re-enable UNREACHABLE once we figure out how to to avoid
|
||||
// the gcc error 'call to non-constexpr function'.
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include "src/maglev/maglev-regalloc.h"
|
||||
|
||||
#include "src/base/bits.h"
|
||||
#include "src/base/logging.h"
|
||||
#include "src/codegen/reglist.h"
|
||||
#include "src/compiler/backend/instruction.h"
|
||||
@ -81,9 +82,6 @@ StraightForwardRegisterAllocator::StraightForwardRegisterAllocator(
|
||||
MaglevCompilationUnit* compilation_unit, Graph* graph)
|
||||
: compilation_unit_(compilation_unit) {
|
||||
ComputePostDominatingHoles(graph);
|
||||
for (int i = 0; i < kAllocatableGeneralRegisterCount; i++) {
|
||||
free_registers_[i] = i;
|
||||
}
|
||||
AllocateRegisters(graph);
|
||||
graph->set_stack_slots(top_of_stack_);
|
||||
}
|
||||
@ -431,9 +429,8 @@ void StraightForwardRegisterAllocator::Free(const Register& reg) {
|
||||
if (node->is_spilled()) return;
|
||||
|
||||
// Try to move the value to another register.
|
||||
if (free_register_size_ > 0) {
|
||||
Register target_reg =
|
||||
MapIndexToRegister(free_registers_[--free_register_size_]);
|
||||
if (free_registers_ != kEmptyRegList) {
|
||||
Register target_reg = Register::TakeAny(&free_registers_);
|
||||
SetRegister(target_reg, node);
|
||||
// Emit a gapmove.
|
||||
compiler::AllocatedOperand source(compiler::LocationOperand::REGISTER,
|
||||
@ -626,7 +623,7 @@ void StraightForwardRegisterAllocator::SpillRegisters() {
|
||||
|
||||
void StraightForwardRegisterAllocator::FreeRegister(int i) {
|
||||
register_values_[i] = nullptr;
|
||||
free_registers_[free_register_size_++] = i;
|
||||
MapIndexToRegister(i).InsertInto(&free_registers_);
|
||||
}
|
||||
|
||||
void StraightForwardRegisterAllocator::SpillAndClearRegisters() {
|
||||
@ -668,7 +665,7 @@ void StraightForwardRegisterAllocator::FreeSomeRegister() {
|
||||
|
||||
compiler::AllocatedOperand StraightForwardRegisterAllocator::AllocateRegister(
|
||||
ValueNode* node) {
|
||||
if (free_register_size_ == 0) FreeSomeRegister();
|
||||
if (free_registers_ == kEmptyRegList) FreeSomeRegister();
|
||||
compiler::InstructionOperand allocation = TryAllocateRegister(node);
|
||||
DCHECK(allocation.IsAllocated());
|
||||
return compiler::AllocatedOperand::cast(allocation);
|
||||
@ -678,13 +675,7 @@ compiler::AllocatedOperand StraightForwardRegisterAllocator::ForceAllocate(
|
||||
const Register& reg, ValueNode* node) {
|
||||
if (register_values_[MapRegisterToIndex(reg)] == nullptr) {
|
||||
// If it's already free, remove it from the free list.
|
||||
// TODO(verwaest): This should just be a mask.
|
||||
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;
|
||||
}
|
||||
}
|
||||
reg.RemoveFrom(&free_registers_);
|
||||
} else if (register_values_[MapRegisterToIndex(reg)] == node) {
|
||||
return compiler::AllocatedOperand(compiler::LocationOperand::REGISTER,
|
||||
MachineRepresentation::kTagged,
|
||||
@ -694,9 +685,8 @@ compiler::AllocatedOperand StraightForwardRegisterAllocator::ForceAllocate(
|
||||
DCHECK_NULL(register_values_[MapRegisterToIndex(reg)]);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
for (int i = 0; i < free_register_size_; i++) {
|
||||
CHECK_NE(MapRegisterToIndex(reg), free_registers_[i]);
|
||||
}
|
||||
DCHECK_NE(free_registers_,
|
||||
CombineRegLists(free_registers_, Register::ListOf(reg)));
|
||||
#endif
|
||||
SetRegister(reg, node);
|
||||
return compiler::AllocatedOperand(compiler::LocationOperand::REGISTER,
|
||||
@ -714,29 +704,28 @@ void StraightForwardRegisterAllocator::SetRegister(Register reg,
|
||||
|
||||
compiler::InstructionOperand
|
||||
StraightForwardRegisterAllocator::TryAllocateRegister(ValueNode* node) {
|
||||
if (free_register_size_ == 0) return compiler::InstructionOperand();
|
||||
int index = free_registers_[--free_register_size_];
|
||||
if (free_registers_ == kEmptyRegList) return compiler::InstructionOperand();
|
||||
Register reg = Register::TakeAny(&free_registers_);
|
||||
|
||||
// Allocation succeeded. This might have found an existing allocation.
|
||||
// Simply update the state anyway.
|
||||
SetRegister(MapIndexToRegister(index), node);
|
||||
SetRegister(reg, node);
|
||||
return compiler::AllocatedOperand(compiler::LocationOperand::REGISTER,
|
||||
MachineRepresentation::kTagged,
|
||||
MapIndexToRegister(index).code());
|
||||
MachineRepresentation::kTagged, reg.code());
|
||||
}
|
||||
|
||||
void StraightForwardRegisterAllocator::AssignTemporaries(NodeBase* node) {
|
||||
int num_temporaries_needed = node->num_temporaries_needed();
|
||||
int num_free_registers = base::bits::CountPopulation(free_registers_);
|
||||
|
||||
RegList free_registers = kEmptyRegList;
|
||||
while (num_temporaries_needed > free_register_size_) 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));
|
||||
// Free extra registers if necessary.
|
||||
for (int i = num_free_registers; i < num_temporaries_needed; ++i) {
|
||||
FreeSomeRegister();
|
||||
}
|
||||
|
||||
node->assign_temporaries(free_registers);
|
||||
DCHECK_GE(base::bits::CountPopulation(free_registers_),
|
||||
num_temporaries_needed);
|
||||
node->assign_temporaries(free_registers_);
|
||||
}
|
||||
|
||||
void StraightForwardRegisterAllocator::InitializeRegisterValues(
|
||||
@ -751,7 +740,7 @@ void StraightForwardRegisterAllocator::InitializeRegisterValues(
|
||||
}
|
||||
|
||||
// Mark no register as free.
|
||||
free_register_size_ = 0;
|
||||
free_registers_ = kEmptyRegList;
|
||||
|
||||
// Then fill it in with target information.
|
||||
for (int i = 0; i < kAllocatableGeneralRegisterCount; i++) {
|
||||
|
@ -31,13 +31,11 @@ class StraightForwardRegisterAllocator {
|
||||
|
||||
#define N(V) nullptr,
|
||||
ValueNode* register_values_[kAllocatableGeneralRegisterCount] = {
|
||||
ALWAYS_ALLOCATABLE_GENERAL_REGISTERS(N)};
|
||||
ALLOCATABLE_GENERAL_REGISTERS(N)};
|
||||
#undef N
|
||||
|
||||
int top_of_stack_ = 0;
|
||||
// TODO(verwaest): Make this a RegList.
|
||||
uint8_t free_register_size_ = kAllocatableGeneralRegisterCount;
|
||||
uint8_t free_registers_[kAllocatableGeneralRegisterCount];
|
||||
RegList free_registers_ = kAllocatableGeneralRegisters;
|
||||
std::vector<uint32_t> free_slots_;
|
||||
|
||||
void ComputePostDominatingHoles(Graph* graph);
|
||||
|
@ -337,7 +337,7 @@ header = '''
|
||||
*/
|
||||
|
||||
#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-inl.h" /* for architecture-specific frame constants */
|
||||
#include "src/objects/contexts.h"
|
||||
@ -359,7 +359,7 @@ STACK_FRAME_TYPE_LIST(FRAME_CONST)
|
||||
|
||||
#undef FRAME_CONST
|
||||
|
||||
''' % sys.argv[0];
|
||||
''' % sys.argv[0]
|
||||
|
||||
footer = '''
|
||||
}
|
||||
@ -440,12 +440,12 @@ def load_objects_from_file(objfilename, checktypes):
|
||||
continue;
|
||||
|
||||
if (in_torque_insttype and (not line or line.isspace())):
|
||||
in_torque_insttype = False
|
||||
continue
|
||||
in_torque_insttype = False
|
||||
continue
|
||||
|
||||
if (in_torque_fulldef and (not line or line.isspace())):
|
||||
in_torque_fulldef = False
|
||||
continue
|
||||
in_torque_fulldef = False
|
||||
continue
|
||||
|
||||
pre = line.strip()
|
||||
line = re.sub('// .*', '', line.strip());
|
||||
@ -497,7 +497,7 @@ def load_objects_from_file(objfilename, checktypes):
|
||||
for entry in entries:
|
||||
entry = entry.strip()
|
||||
if not entry:
|
||||
continue
|
||||
continue
|
||||
start = entry.find('(');
|
||||
end = entry.find(')', start);
|
||||
rest = entry[start + 1: end];
|
||||
|
Loading…
Reference in New Issue
Block a user