[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:
Leszek Swirski 2022-03-03 10:52:32 +01:00 committed by V8 LUCI CQ
parent 89f02d7808
commit 31abbcfb4d
31 changed files with 227 additions and 229 deletions

View File

@ -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",

View File

@ -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",

View File

@ -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"

View File

@ -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 {

View File

@ -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"

View File

@ -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 {

View File

@ -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"

View File

@ -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"

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

View File

@ -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
View 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_

View File

@ -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 {

View File

@ -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_

View File

@ -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"

View File

@ -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 {

View File

@ -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"

View File

@ -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 {

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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
};

View File

@ -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());

View File

@ -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'.

View File

@ -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++) {

View File

@ -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);

View File

@ -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];