[codegen] Change RegList into a class

Modernise the RegList interface to be a proper class, rather than a
typedef to an integer, and add proper methods onto it rather than ad-hoc
bit manipulation.

In particular, this makes RegList typesafe, adding a DoubleRegList for
DoubleRegisters.

The Arm64 CPURegList isn't updated to use (or extend) the new RegList
interface, because of its weird type-erasing semantics (it can store
Registers and VRegisters). Maybe in the future we'll want to get rid of
CPURegList entirely and use RegList/DoubleRegList directly.

Change-Id: I3cb2a4d386cb92a4dcd2edbdd3fba9ef71f354d6
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3516747
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: Camillo Bruni <cbruni@chromium.org>
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/main@{#79460}
This commit is contained in:
Leszek Swirski 2022-03-14 13:14:35 +01:00 committed by V8 LUCI CQ
parent 5a968b08b3
commit 8a0d1b6fe5
138 changed files with 2127 additions and 2253 deletions

View File

@ -1116,10 +1116,12 @@ 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",
"src/codegen/reglist-base.h",
"src/codegen/reglist.h",
"src/codegen/reloc-info.cc",
"src/codegen/reloc-info.h",
@ -2102,6 +2104,7 @@ filegroup(
"src/codegen/ia32/macro-assembler-ia32.cc",
"src/codegen/ia32/macro-assembler-ia32.h",
"src/codegen/ia32/register-ia32.h",
"src/codegen/ia32/reglist-ia32.h",
"src/compiler/backend/ia32/code-generator-ia32.cc",
"src/compiler/backend/ia32/instruction-codes-ia32.h",
"src/compiler/backend/ia32/instruction-scheduler-ia32.cc",
@ -2131,6 +2134,7 @@ filegroup(
"src/codegen/x64/macro-assembler-x64.cc",
"src/codegen/x64/macro-assembler-x64.h",
"src/codegen/x64/register-x64.h",
"src/codegen/x64/reglist-x64.h",
"src/compiler/backend/x64/code-generator-x64.cc",
"src/compiler/backend/x64/instruction-codes-x64.h",
"src/compiler/backend/x64/instruction-scheduler-x64.cc",
@ -2160,6 +2164,7 @@ filegroup(
"src/codegen/arm/macro-assembler-arm.cc",
"src/codegen/arm/macro-assembler-arm.h",
"src/codegen/arm/register-arm.h",
"src/codegen/arm/reglist-arm.h",
"src/compiler/backend/arm/code-generator-arm.cc",
"src/compiler/backend/arm/instruction-codes-arm.h",
"src/compiler/backend/arm/instruction-scheduler-arm.cc",
@ -2198,6 +2203,7 @@ filegroup(
"src/codegen/arm64/macro-assembler-arm64.h",
"src/codegen/arm64/register-arm64.cc",
"src/codegen/arm64/register-arm64.h",
"src/codegen/arm64/reglist-arm64.h",
"src/codegen/arm64/utils-arm64.cc",
"src/codegen/arm64/utils-arm64.h",
"src/compiler/backend/arm64/code-generator-arm64.cc",
@ -2234,6 +2240,7 @@ filegroup(
"src/codegen/s390/macro-assembler-s390.cc",
"src/codegen/s390/macro-assembler-s390.h",
"src/codegen/s390/register-s390.h",
"src/codegen/s390/reglist-s390.h",
"src/compiler/backend/s390/code-generator-s390.cc",
"src/compiler/backend/s390/instruction-codes-s390.h",
"src/compiler/backend/s390/instruction-scheduler-s390.cc",
@ -2265,6 +2272,7 @@ filegroup(
"src/codegen/riscv64/macro-assembler-riscv64.cc",
"src/codegen/riscv64/macro-assembler-riscv64.h",
"src/codegen/riscv64/register-riscv64.h",
"src/codegen/riscv64/reglist-riscv64.h",
"src/compiler/backend/riscv64/code-generator-riscv64.cc",
"src/compiler/backend/riscv64/instruction-codes-riscv64.h",
"src/compiler/backend/riscv64/instruction-scheduler-riscv64.cc",
@ -2293,6 +2301,7 @@ filegroup(
"src/codegen/ppc/macro-assembler-ppc.cc",
"src/codegen/ppc/macro-assembler-ppc.h",
"src/codegen/ppc/register-ppc.h",
"src/codegen/ppc/reglist-ppc.h",
"src/compiler/backend/ppc/code-generator-ppc.cc",
"src/compiler/backend/ppc/instruction-codes-ppc.h",
"src/compiler/backend/ppc/instruction-scheduler-ppc.cc",

View File

@ -2728,9 +2728,11 @@ 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-base.h",
"src/codegen/reglist.h",
"src/codegen/reloc-info.h",
"src/codegen/safepoint-table.h",
@ -3629,6 +3631,7 @@ v8_header_set("v8_internal_headers") {
"src/codegen/ia32/interface-descriptors-ia32-inl.h",
"src/codegen/ia32/macro-assembler-ia32.h",
"src/codegen/ia32/register-ia32.h",
"src/codegen/ia32/reglist-ia32.h",
"src/codegen/ia32/sse-instr.h",
"src/codegen/shared-ia32-x64/macro-assembler-shared-ia32-x64.h",
"src/compiler/backend/ia32/instruction-codes-ia32.h",
@ -3648,6 +3651,7 @@ v8_header_set("v8_internal_headers") {
"src/codegen/x64/interface-descriptors-x64-inl.h",
"src/codegen/x64/macro-assembler-x64.h",
"src/codegen/x64/register-x64.h",
"src/codegen/x64/reglist-x64.h",
"src/codegen/x64/sse-instr.h",
"src/compiler/backend/x64/instruction-codes-x64.h",
"src/compiler/backend/x64/unwinding-info-writer-x64.h",
@ -3681,6 +3685,7 @@ v8_header_set("v8_internal_headers") {
"src/codegen/arm/interface-descriptors-arm-inl.h",
"src/codegen/arm/macro-assembler-arm.h",
"src/codegen/arm/register-arm.h",
"src/codegen/arm/reglist-arm.h",
"src/compiler/backend/arm/instruction-codes-arm.h",
"src/compiler/backend/arm/unwinding-info-writer-arm.h",
"src/execution/arm/frame-constants-arm.h",
@ -3702,6 +3707,7 @@ v8_header_set("v8_internal_headers") {
"src/codegen/arm64/macro-assembler-arm64-inl.h",
"src/codegen/arm64/macro-assembler-arm64.h",
"src/codegen/arm64/register-arm64.h",
"src/codegen/arm64/reglist-arm64.h",
"src/codegen/arm64/utils-arm64.h",
"src/compiler/backend/arm64/instruction-codes-arm64.h",
"src/compiler/backend/arm64/unwinding-info-writer-arm64.h",
@ -3738,6 +3744,7 @@ v8_header_set("v8_internal_headers") {
"src/codegen/mips/constants-mips.h",
"src/codegen/mips/macro-assembler-mips.h",
"src/codegen/mips/register-mips.h",
"src/codegen/mips/reglist-mips.h",
"src/compiler/backend/mips/instruction-codes-mips.h",
"src/execution/mips/frame-constants-mips.h",
"src/execution/mips/simulator-mips.h",
@ -3753,6 +3760,7 @@ v8_header_set("v8_internal_headers") {
"src/codegen/mips64/constants-mips64.h",
"src/codegen/mips64/macro-assembler-mips64.h",
"src/codegen/mips64/register-mips64.h",
"src/codegen/mips64/reglist-mips64.h",
"src/compiler/backend/mips64/instruction-codes-mips64.h",
"src/execution/mips64/frame-constants-mips64.h",
"src/execution/mips64/simulator-mips64.h",
@ -3768,6 +3776,7 @@ v8_header_set("v8_internal_headers") {
"src/codegen/loong64/constants-loong64.h",
"src/codegen/loong64/macro-assembler-loong64.h",
"src/codegen/loong64/register-loong64.h",
"src/codegen/loong64/reglist-loong64.h",
"src/compiler/backend/loong64/instruction-codes-loong64.h",
"src/execution/loong64/frame-constants-loong64.h",
"src/execution/loong64/simulator-loong64.h",
@ -3782,6 +3791,7 @@ v8_header_set("v8_internal_headers") {
"src/codegen/ppc/interface-descriptors-ppc-inl.h",
"src/codegen/ppc/macro-assembler-ppc.h",
"src/codegen/ppc/register-ppc.h",
"src/codegen/ppc/reglist-ppc.h",
"src/compiler/backend/ppc/instruction-codes-ppc.h",
"src/compiler/backend/ppc/unwinding-info-writer-ppc.h",
"src/execution/ppc/frame-constants-ppc.h",
@ -3799,6 +3809,7 @@ v8_header_set("v8_internal_headers") {
"src/codegen/ppc/interface-descriptors-ppc-inl.h",
"src/codegen/ppc/macro-assembler-ppc.h",
"src/codegen/ppc/register-ppc.h",
"src/codegen/ppc/reglist-ppc.h",
"src/compiler/backend/ppc/instruction-codes-ppc.h",
"src/compiler/backend/ppc/unwinding-info-writer-ppc.h",
"src/execution/ppc/frame-constants-ppc.h",
@ -3816,6 +3827,7 @@ v8_header_set("v8_internal_headers") {
"src/codegen/s390/interface-descriptors-s390-inl.h",
"src/codegen/s390/macro-assembler-s390.h",
"src/codegen/s390/register-s390.h",
"src/codegen/s390/reglist-s390.h",
"src/compiler/backend/s390/instruction-codes-s390.h",
"src/compiler/backend/s390/unwinding-info-writer-s390.h",
"src/execution/s390/frame-constants-s390.h",
@ -3832,6 +3844,7 @@ v8_header_set("v8_internal_headers") {
"src/codegen/riscv64/constants-riscv64.h",
"src/codegen/riscv64/macro-assembler-riscv64.h",
"src/codegen/riscv64/register-riscv64.h",
"src/codegen/riscv64/reglist-riscv64.h",
"src/compiler/backend/riscv64/instruction-codes-riscv64.h",
"src/execution/riscv64/frame-constants-riscv64.h",
"src/execution/riscv64/simulator-riscv64.h",

View File

@ -22,7 +22,7 @@ class BaselineAssembler::ScratchRegisterScope {
if (!assembler_->scratch_register_scope_) {
// If we haven't opened a scratch scope yet, for the first one add a
// couple of extra registers.
wrapped_scope_.Include(t0.bit() | t1.bit() | t2.bit() | t3.bit());
wrapped_scope_.Include({t0, t1, t2, t3});
}
assembler_->scratch_register_scope_ = this;
}

View File

@ -22,7 +22,7 @@ class BaselineAssembler::ScratchRegisterScope {
if (!assembler_->scratch_register_scope_) {
// If we haven't opened a scratch scope yet, for the first one add a
// couple of extra registers.
wrapped_scope_.Include(t4.bit() | t5.bit() | t6.bit() | t7.bit());
wrapped_scope_.Include({t4, t5, t6, t7});
}
assembler_->scratch_register_scope_ = this;
}

View File

@ -22,7 +22,7 @@ class BaselineAssembler::ScratchRegisterScope {
if (!assembler_->scratch_register_scope_) {
// If we haven't opened a scratch scope yet, for the first one add a
// couple of extra registers.
wrapped_scope_.Include(t0.bit() | t1.bit() | t2.bit() | t3.bit());
wrapped_scope_.Include({t0, t1, t2, t3});
}
assembler_->scratch_register_scope_ = this;
}

View File

@ -555,7 +555,7 @@ void Generate_JSEntryVariant(MacroAssembler* masm, StackFrame::Type type,
// r1: microtask_queue
// Preserve all but r0 and pass them to entry_trampoline.
Label invoke, handler_entry, exit;
const RegList kCalleeSavedWithoutFp = kCalleeSaved & ~fp.bit();
const RegList kCalleeSavedWithoutFp = kCalleeSaved - fp;
// Update |pushed_stack_space| when we manipulate the stack.
int pushed_stack_space = EntryFrameConstants::kCallerFPOffset;
@ -589,7 +589,7 @@ void Generate_JSEntryVariant(MacroAssembler* masm, StackFrame::Type type,
masm->isolate()));
__ ldr(r5, MemOperand(r4));
__ stm(db_w, sp, r5.bit() | r6.bit() | r7.bit() | fp.bit() | lr.bit());
__ stm(db_w, sp, {r5, r6, r7, fp, lr});
pushed_stack_space += 5 * kPointerSize /* r5, r6, r7, fp, lr */;
// Clear c_entry_fp, now we've pushed its previous value to the stack.
@ -690,7 +690,7 @@ void Generate_JSEntryVariant(MacroAssembler* masm, StackFrame::Type type,
Operand(-EntryFrameConstants::kCallerFPOffset -
kSystemPointerSize /* already popped one */));
__ ldm(ia_w, sp, fp.bit() | lr.bit());
__ ldm(ia_w, sp, {fp, lr});
// Restore callee-saved vfp registers.
__ vldm(ia_w, sp, kFirstCalleeSavedDoubleReg, kLastCalleeSavedDoubleReg);
@ -1202,7 +1202,7 @@ void Builtins::Generate_BaselineOutOfLinePrologue(MacroAssembler* masm) {
temps.Exclude(optimization_state);
// Drop the frame created by the baseline call.
__ ldm(ia_w, sp, fp.bit() | lr.bit());
__ ldm(ia_w, sp, {fp, lr});
MaybeOptimizeCodeOrTailCallOptimizedCodeSlot(masm, optimization_state,
feedback_vector);
__ Trap();
@ -2628,9 +2628,9 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
// Save all parameter registers (see wasm-linkage.h). They might be
// overwritten in the runtime call below. We don't have any callee-saved
// registers in wasm, so no need to store anything else.
RegList gp_regs = 0;
RegList gp_regs;
for (Register gp_param_reg : wasm::kGpParamRegisters) {
gp_regs |= gp_param_reg.bit();
gp_regs.set(gp_param_reg);
}
DwVfpRegister lowest_fp_reg = std::begin(wasm::kFpParamRegisters)[0];
DwVfpRegister highest_fp_reg = std::end(wasm::kFpParamRegisters)[-1];
@ -2639,10 +2639,10 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
fp_param_reg.code() <= highest_fp_reg.code());
}
CHECK_EQ(NumRegs(gp_regs), arraysize(wasm::kGpParamRegisters));
CHECK_EQ(gp_regs.Count(), arraysize(wasm::kGpParamRegisters));
CHECK_EQ(highest_fp_reg.code() - lowest_fp_reg.code() + 1,
arraysize(wasm::kFpParamRegisters));
CHECK_EQ(NumRegs(gp_regs),
CHECK_EQ(gp_regs.Count(),
WasmCompileLazyFrameConstants::kNumberOfSavedGpParamRegs);
CHECK_EQ(highest_fp_reg.code() - lowest_fp_reg.code() + 1,
WasmCompileLazyFrameConstants::kNumberOfSavedFpParamRegs);
@ -2675,20 +2675,19 @@ void Builtins::Generate_WasmDebugBreak(MacroAssembler* masm) {
FrameAndConstantPoolScope scope(masm, StackFrame::WASM_DEBUG_BREAK);
STATIC_ASSERT(DwVfpRegister::kNumRegisters == 32);
constexpr uint32_t last =
31 - base::bits::CountLeadingZeros32(
WasmDebugBreakFrameConstants::kPushedFpRegs);
constexpr uint32_t first = base::bits::CountTrailingZeros32(
WasmDebugBreakFrameConstants::kPushedFpRegs);
constexpr DwVfpRegister last =
WasmDebugBreakFrameConstants::kPushedFpRegs.last();
constexpr DwVfpRegister first =
WasmDebugBreakFrameConstants::kPushedFpRegs.first();
static_assert(
base::bits::CountPopulation(
WasmDebugBreakFrameConstants::kPushedFpRegs) == last - first + 1,
WasmDebugBreakFrameConstants::kPushedFpRegs.Count() ==
last.code() - first.code() + 1,
"All registers in the range from first to last have to be set");
// Save all parameter registers. They might hold live values, we restore
// them after the runtime call.
constexpr DwVfpRegister lowest_fp_reg = DwVfpRegister::from_code(first);
constexpr DwVfpRegister highest_fp_reg = DwVfpRegister::from_code(last);
constexpr DwVfpRegister lowest_fp_reg = first;
constexpr DwVfpRegister highest_fp_reg = last;
// Store gp parameter registers.
__ stm(db_w, sp, WasmDebugBreakFrameConstants::kPushedGpRegs);
@ -3340,12 +3339,12 @@ void Generate_DeoptimizationEntry(MacroAssembler* masm,
STATIC_ASSERT(kNumberOfRegisters == 16);
// Everything but pc, lr and ip which will be saved but not restored.
RegList restored_regs = kJSCallerSaved | kCalleeSaved | ip.bit();
RegList restored_regs = kJSCallerSaved | kCalleeSaved | RegList{ip};
// Push all 16 registers (needed to populate FrameDescription::registers_).
// TODO(v8:1588): Note that using pc with stm is deprecated, so we should
// perhaps handle this a bit differently.
__ stm(db_w, sp, restored_regs | sp.bit() | lr.bit() | pc.bit());
__ stm(db_w, sp, restored_regs | RegList{sp, lr, pc});
{
UseScratchRegisterScope temps(masm);

View File

@ -3037,27 +3037,27 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
// Save all parameter registers (see wasm-linkage.h). They might be
// overwritten in the runtime call below. We don't have any callee-saved
// registers in wasm, so no need to store anything else.
RegList gp_regs = 0;
RegList gp_regs;
for (Register gp_param_reg : wasm::kGpParamRegisters) {
gp_regs |= gp_param_reg.bit();
gp_regs.set(gp_param_reg);
}
// Also push x1, because we must push multiples of 16 bytes (see
// {TurboAssembler::PushCPURegList}.
CHECK_EQ(1, NumRegs(gp_regs) % 2);
gp_regs |= x1.bit();
CHECK_EQ(0, NumRegs(gp_regs) % 2);
CHECK_EQ(1, gp_regs.Count() % 2);
gp_regs.set(x1);
CHECK_EQ(0, gp_regs.Count() % 2);
RegList fp_regs = 0;
DoubleRegList fp_regs;
for (DoubleRegister fp_param_reg : wasm::kFpParamRegisters) {
fp_regs |= fp_param_reg.bit();
fp_regs.set(fp_param_reg);
}
CHECK_EQ(NumRegs(gp_regs), arraysize(wasm::kGpParamRegisters) + 1);
CHECK_EQ(NumRegs(fp_regs), arraysize(wasm::kFpParamRegisters));
CHECK_EQ(gp_regs.Count(), arraysize(wasm::kGpParamRegisters) + 1);
CHECK_EQ(fp_regs.Count(), arraysize(wasm::kFpParamRegisters));
CHECK_EQ(WasmCompileLazyFrameConstants::kNumberOfSavedGpParamRegs,
NumRegs(gp_regs));
gp_regs.Count());
CHECK_EQ(WasmCompileLazyFrameConstants::kNumberOfSavedFpParamRegs,
NumRegs(fp_regs));
fp_regs.Count());
__ PushXRegList(gp_regs);
__ PushQRegList(fp_regs);
@ -3868,8 +3868,9 @@ void Generate_DeoptimizationEntry(MacroAssembler* masm,
// Save all allocatable double registers.
CPURegList saved_double_registers(
CPURegister::kVRegister, kDRegSizeInBits,
RegisterConfiguration::Default()->allocatable_double_codes_mask());
kDRegSizeInBits,
DoubleRegList::FromBits(
RegisterConfiguration::Default()->allocatable_double_codes_mask()));
DCHECK_EQ(saved_double_registers.Count() % 2, 0);
__ PushCPURegList(saved_double_registers);
@ -4273,7 +4274,9 @@ void Builtins::Generate_DynamicCheckMapsTrampoline(
RegList registers = descriptor.allocatable_registers();
// FLAG_debug_code is enabled CSA checks will call C function and so we need
// to save all CallerSaved registers too.
if (FLAG_debug_code) registers |= kCallerSaved.list();
if (FLAG_debug_code) {
registers |= RegList::FromBits(static_cast<uint32_t>(kCallerSaved.bits()));
}
__ MaybeSaveRegisters(registers);
// Load the immediate arguments from the deopt exit to pass to the builtin.

View File

@ -2923,19 +2923,19 @@ void Builtins::Generate_WasmDebugBreak(MacroAssembler* masm) {
// Save all parameter registers. They might hold live values, we restore
// them after the runtime call.
for (int reg_code : base::bits::IterateBitsBackwards(
WasmDebugBreakFrameConstants::kPushedGpRegs)) {
__ Push(Register::from_code(reg_code));
for (Register reg :
base::Reversed(WasmDebugBreakFrameConstants::kPushedGpRegs)) {
__ Push(reg);
}
constexpr int kFpStackSize =
kSimd128Size * WasmDebugBreakFrameConstants::kNumPushedFpRegisters;
__ AllocateStackSpace(kFpStackSize);
int offset = kFpStackSize;
for (int reg_code : base::bits::IterateBitsBackwards(
WasmDebugBreakFrameConstants::kPushedFpRegs)) {
for (DoubleRegister reg :
base::Reversed(WasmDebugBreakFrameConstants::kPushedFpRegs)) {
offset -= kSimd128Size;
__ movdqu(Operand(esp, offset), DoubleRegister::from_code(reg_code));
__ movdqu(Operand(esp, offset), reg);
}
// Initialize the JavaScript context with 0. CEntry will use it to
@ -2944,15 +2944,13 @@ void Builtins::Generate_WasmDebugBreak(MacroAssembler* masm) {
__ CallRuntime(Runtime::kWasmDebugBreak, 0);
// Restore registers.
for (int reg_code :
base::bits::IterateBits(WasmDebugBreakFrameConstants::kPushedFpRegs)) {
__ movdqu(DoubleRegister::from_code(reg_code), Operand(esp, offset));
for (DoubleRegister reg : WasmDebugBreakFrameConstants::kPushedFpRegs) {
__ movdqu(reg, Operand(esp, offset));
offset += kSimd128Size;
}
__ add(esp, Immediate(kFpStackSize));
for (int reg_code :
base::bits::IterateBits(WasmDebugBreakFrameConstants::kPushedGpRegs)) {
__ Pop(Register::from_code(reg_code));
for (Register reg : WasmDebugBreakFrameConstants::kPushedGpRegs) {
__ Pop(reg);
}
}

View File

@ -553,7 +553,7 @@ void Generate_JSEntryVariant(MacroAssembler* masm, StackFrame::Type type,
// a1: microtask_queue
// Save callee saved registers on the stack.
__ MultiPush(kCalleeSaved | ra.bit());
__ MultiPush(kCalleeSaved | ra);
// Save callee-saved FPU registers.
__ MultiPushFPU(kCalleeSavedFPU);
@ -707,7 +707,7 @@ void Generate_JSEntryVariant(MacroAssembler* masm, StackFrame::Type type,
__ MultiPopFPU(kCalleeSavedFPU);
// Restore callee saved registers from the stack.
__ MultiPop(kCalleeSaved | ra.bit());
__ MultiPop(kCalleeSaved | ra);
// Return.
__ Jump(ra);
}
@ -1053,8 +1053,8 @@ static void MaybeOptimizeCodeOrTailCallOptimizedCodeSlot(
// static
void Builtins::Generate_BaselineOutOfLinePrologue(MacroAssembler* masm) {
UseScratchRegisterScope temps(masm);
temps.Include(s1.bit() | s2.bit());
temps.Exclude(t7.bit());
temps.Include({s1, s2});
temps.Exclude({t7});
auto descriptor =
Builtins::CallInterfaceDescriptorFor(Builtin::kBaselineOutOfLinePrologue);
Register closure = descriptor.GetRegisterParameter(
@ -1197,7 +1197,7 @@ void Builtins::Generate_BaselineOutOfLinePrologue(MacroAssembler* masm) {
__ Pop(kJavaScriptCallNewTargetRegister);
}
__ Ret();
temps.Exclude(s1.bit() | s2.bit());
temps.Exclude({s1, s2});
}
// Generate code for entering a JS function with the interpreter.
@ -2664,22 +2664,22 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
// Save all parameter registers (see wasm-linkage.h). They might be
// overwritten in the runtime call below. We don't have any callee-saved
// registers in wasm, so no need to store anything else.
RegList gp_regs = 0;
RegList gp_regs;
for (Register gp_param_reg : wasm::kGpParamRegisters) {
gp_regs |= gp_param_reg.bit();
gp_regs.set(gp_param_reg);
}
RegList fp_regs = 0;
RegList fp_regs;
for (DoubleRegister fp_param_reg : wasm::kFpParamRegisters) {
fp_regs |= fp_param_reg.bit();
fp_regs.set(fp_param_reg);
}
CHECK_EQ(NumRegs(gp_regs), arraysize(wasm::kGpParamRegisters));
CHECK_EQ(NumRegs(fp_regs), arraysize(wasm::kFpParamRegisters));
CHECK_EQ(gp_regs.Count(), arraysize(wasm::kGpParamRegisters));
CHECK_EQ(fp_regs.Count(), arraysize(wasm::kFpParamRegisters));
CHECK_EQ(WasmCompileLazyFrameConstants::kNumberOfSavedGpParamRegs,
NumRegs(gp_regs));
gp_regs.Count());
CHECK_EQ(WasmCompileLazyFrameConstants::kNumberOfSavedFpParamRegs,
NumRegs(fp_regs));
fp_regs.Count());
__ MultiPush(gp_regs);
__ MultiPushFPU(fp_regs);
@ -3375,7 +3375,7 @@ void Generate_DeoptimizationEntry(MacroAssembler* masm,
const int kNumberOfRegisters = Register::kNumRegisters;
RegList restored_regs = kJSCallerSaved | kCalleeSaved;
RegList saved_regs = restored_regs | sp.bit() | ra.bit();
RegList saved_regs = restored_regs | sp | ra;
const int kDoubleRegsSize = kDoubleSize * DoubleRegister::kNumRegisters;
@ -3539,7 +3539,7 @@ void Generate_DeoptimizationEntry(MacroAssembler* masm,
// Technically restoring 'at' should work unless zero_reg is also restored
// but it's safer to check for this.
DCHECK(!(t7.bit() & restored_regs));
DCHECK(!(restored_regs.has(t7)));
// Restore the registers from the last output frame.
__ mov(t7, a2);
for (int i = kNumberOfRegisters - 1; i >= 0; i--) {

View File

@ -390,7 +390,7 @@ void Generate_JSEntryVariant(MacroAssembler* masm, StackFrame::Type type,
// a0: root_register_value
// Save callee saved registers on the stack.
__ MultiPush(kCalleeSaved | ra.bit());
__ MultiPush(kCalleeSaved | ra);
pushed_stack_space +=
kNumCalleeSaved * kPointerSize + kPointerSize /* ra */;
@ -524,7 +524,7 @@ void Generate_JSEntryVariant(MacroAssembler* masm, StackFrame::Type type,
__ MultiPopFPU(kCalleeSavedFPU);
// Restore callee saved registers from the stack.
__ MultiPop(kCalleeSaved | ra.bit());
__ MultiPop(kCalleeSaved | ra);
// Return.
__ Jump(ra);
}
@ -1052,7 +1052,7 @@ static void MaybeOptimizeCodeOrTailCallOptimizedCodeSlot(
// static
void Builtins::Generate_BaselineOutOfLinePrologue(MacroAssembler* masm) {
UseScratchRegisterScope temps(masm);
temps.Include(s1.bit() | s2.bit());
temps.Include({s1, s2});
auto descriptor =
Builtins::CallInterfaceDescriptorFor(Builtin::kBaselineOutOfLinePrologue);
Register closure = descriptor.GetRegisterParameter(
@ -1193,7 +1193,7 @@ void Builtins::Generate_BaselineOutOfLinePrologue(MacroAssembler* masm) {
__ Pop(kJavaScriptCallNewTargetRegister);
}
__ Ret();
temps.Exclude(kScratchReg.bit() | kScratchReg2.bit());
temps.Exclude({kScratchReg, kScratchReg2});
}
// Generate code for entering a JS function with the interpreter.
@ -2608,22 +2608,22 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
// Save all parameter registers (see wasm-linkage.h). They might be
// overwritten in the runtime call below. We don't have any callee-saved
// registers in wasm, so no need to store anything else.
RegList gp_regs = 0;
RegList gp_regs;
for (Register gp_param_reg : wasm::kGpParamRegisters) {
gp_regs |= gp_param_reg.bit();
gp_regs.set(gp_param_reg);
}
RegList fp_regs = 0;
RegList fp_regs;
for (DoubleRegister fp_param_reg : wasm::kFpParamRegisters) {
fp_regs |= fp_param_reg.bit();
fp_regs.set(fp_param_reg);
}
CHECK_EQ(NumRegs(gp_regs), arraysize(wasm::kGpParamRegisters));
CHECK_EQ(NumRegs(fp_regs), arraysize(wasm::kFpParamRegisters));
CHECK_EQ(gp_regs.Count(), arraysize(wasm::kGpParamRegisters));
CHECK_EQ(fp_regs.Count(), arraysize(wasm::kFpParamRegisters));
CHECK_EQ(WasmCompileLazyFrameConstants::kNumberOfSavedGpParamRegs,
NumRegs(gp_regs));
gp_regs.Count());
CHECK_EQ(WasmCompileLazyFrameConstants::kNumberOfSavedFpParamRegs,
NumRegs(fp_regs));
fp_regs.Count());
__ MultiPush(gp_regs);
__ MultiPushFPU(fp_regs);
@ -3821,7 +3821,7 @@ void Generate_DeoptimizationEntry(MacroAssembler* masm,
static constexpr int kNumberOfRegisters = Register::kNumRegisters;
RegList restored_regs = kJSCallerSaved | kCalleeSaved;
RegList saved_regs = restored_regs | sp.bit() | ra.bit();
RegList saved_regs = restored_regs | sp | ra;
static constexpr int kDoubleRegsSize =
kDoubleSize * DoubleRegister::kNumRegisters;
@ -3987,7 +3987,7 @@ void Generate_DeoptimizationEntry(MacroAssembler* masm,
// Technically restoring 'at' should work unless zero_reg is also restored
// but it's safer to check for this.
DCHECK(!(at.bit() & restored_regs));
DCHECK(!(restored_regs.has(at)));
// Restore the registers from the last output frame.
__ mov(at, a2);
for (int i = kNumberOfRegisters - 1; i >= 0; i--) {

View File

@ -556,7 +556,7 @@ void Generate_JSEntryVariant(MacroAssembler* masm, StackFrame::Type type,
// 0 arg slots on mips64 (4 args slots on mips)
// Save callee saved registers on the stack.
__ MultiPush(kCalleeSaved | ra.bit());
__ MultiPush(kCalleeSaved | ra);
// Save callee-saved FPU registers.
__ MultiPushFPU(kCalleeSavedFPU);
@ -709,7 +709,7 @@ void Generate_JSEntryVariant(MacroAssembler* masm, StackFrame::Type type,
__ MultiPopFPU(kCalleeSavedFPU);
// Restore callee saved registers from the stack.
__ MultiPop(kCalleeSaved | ra.bit());
__ MultiPop(kCalleeSaved | ra);
// Return.
__ Jump(ra);
}
@ -1059,7 +1059,7 @@ static void MaybeOptimizeCodeOrTailCallOptimizedCodeSlot(
// static
void Builtins::Generate_BaselineOutOfLinePrologue(MacroAssembler* masm) {
UseScratchRegisterScope temps(masm);
temps.Include(s1.bit() | s2.bit());
temps.Include({s1, s2});
auto descriptor =
Builtins::CallInterfaceDescriptorFor(Builtin::kBaselineOutOfLinePrologue);
Register closure = descriptor.GetRegisterParameter(
@ -1200,7 +1200,7 @@ void Builtins::Generate_BaselineOutOfLinePrologue(MacroAssembler* masm) {
__ Pop(kJavaScriptCallNewTargetRegister);
}
__ Ret();
temps.Exclude(kScratchReg.bit() | kScratchReg2.bit());
temps.Exclude({kScratchReg, kScratchReg2});
}
// Generate code for entering a JS function with the interpreter.
@ -2658,22 +2658,22 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
// Save all parameter registers (see wasm-linkage.h). They might be
// overwritten in the runtime call below. We don't have any callee-saved
// registers in wasm, so no need to store anything else.
RegList gp_regs = 0;
RegList gp_regs;
for (Register gp_param_reg : wasm::kGpParamRegisters) {
gp_regs |= gp_param_reg.bit();
gp_regs.set(gp_param_reg);
}
RegList fp_regs = 0;
RegList fp_regs;
for (DoubleRegister fp_param_reg : wasm::kFpParamRegisters) {
fp_regs |= fp_param_reg.bit();
fp_regs.set(fp_param_reg);
}
CHECK_EQ(NumRegs(gp_regs), arraysize(wasm::kGpParamRegisters));
CHECK_EQ(NumRegs(fp_regs), arraysize(wasm::kFpParamRegisters));
CHECK_EQ(gp_regs.Count(), arraysize(wasm::kGpParamRegisters));
CHECK_EQ(fp_regs.Count(), arraysize(wasm::kFpParamRegisters));
CHECK_EQ(WasmCompileLazyFrameConstants::kNumberOfSavedGpParamRegs,
NumRegs(gp_regs));
gp_regs.Count());
CHECK_EQ(WasmCompileLazyFrameConstants::kNumberOfSavedFpParamRegs,
NumRegs(fp_regs));
fp_regs.Count());
__ MultiPush(gp_regs);
// Check if machine has simd enabled, if so push vector registers. If not
@ -3400,7 +3400,7 @@ void Generate_DeoptimizationEntry(MacroAssembler* masm,
const int kNumberOfRegisters = Register::kNumRegisters;
RegList restored_regs = kJSCallerSaved | kCalleeSaved;
RegList saved_regs = restored_regs | sp.bit() | ra.bit();
RegList saved_regs = restored_regs | sp | ra;
const int kDoubleRegsSize = kDoubleSize * DoubleRegister::kNumRegisters;
@ -3565,7 +3565,7 @@ void Generate_DeoptimizationEntry(MacroAssembler* masm,
// Technically restoring 'at' should work unless zero_reg is also restored
// but it's safer to check for this.
DCHECK(!(at.bit() & restored_regs));
DCHECK(!(restored_regs.has(at)));
// Restore the registers from the last output frame.
__ mov(at, a2);
for (int i = kNumberOfRegisters - 1; i >= 0; i--) {

View File

@ -2470,29 +2470,28 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
// Save all parameter registers (see wasm-linkage.h). They might be
// overwritten in the runtime call below. We don't have any callee-saved
// registers in wasm, so no need to store anything else.
RegList gp_regs = 0;
RegList gp_regs;
for (Register gp_param_reg : wasm::kGpParamRegisters) {
gp_regs |= gp_param_reg.bit();
gp_regs.set(gp_param_reg);
}
RegList fp_regs = 0;
RegList fp_regs;
for (DoubleRegister fp_param_reg : wasm::kFpParamRegisters) {
fp_regs |= fp_param_reg.bit();
fp_regs.set(fp_param_reg);
}
// List must match register numbers under kFpParamRegisters.
constexpr RegList simd_regs =
Simd128Register::ListOf(v1, v2, v3, v4, v5, v6, v7, v8);
constexpr RegList simd_regs = {v1, v2, v3, v4, v5, v6, v7, v8};
CHECK_EQ(NumRegs(gp_regs), arraysize(wasm::kGpParamRegisters));
CHECK_EQ(NumRegs(fp_regs), arraysize(wasm::kFpParamRegisters));
CHECK_EQ(NumRegs(simd_regs), arraysize(wasm::kFpParamRegisters));
CHECK_EQ(gp_regs.Count(), arraysize(wasm::kGpParamRegisters));
CHECK_EQ(fp_regs.Count(), arraysize(wasm::kFpParamRegisters));
CHECK_EQ(simd_regs.Count(), arraysize(wasm::kFpParamRegisters));
CHECK_EQ(WasmCompileLazyFrameConstants::kNumberOfSavedGpParamRegs,
NumRegs(gp_regs));
gp_regs.Count());
CHECK_EQ(WasmCompileLazyFrameConstants::kNumberOfSavedFpParamRegs,
NumRegs(fp_regs));
fp_regs.Count());
CHECK_EQ(WasmCompileLazyFrameConstants::kNumberOfSavedFpParamRegs,
NumRegs(simd_regs));
simd_regs.Count());
__ MultiPush(gp_regs);
__ MultiPushF64AndV128(fp_regs, simd_regs);
@ -3246,7 +3245,7 @@ void Generate_DeoptimizationEntry(MacroAssembler* masm,
const int kNumberOfRegisters = Register::kNumRegisters;
RegList restored_regs = kJSCallerSaved | kCalleeSaved;
RegList saved_regs = restored_regs | sp.bit();
RegList saved_regs = restored_regs | sp;
const int kDoubleRegsSize = kDoubleSize * DoubleRegister::kNumRegisters;
@ -3429,7 +3428,7 @@ void Generate_DeoptimizationEntry(MacroAssembler* masm,
{
UseScratchRegisterScope temps(masm);
Register scratch = temps.Acquire();
DCHECK(!(scratch.bit() & restored_regs));
DCHECK(!(restored_regs.has(scratch)));
__ mr(scratch, r5);
for (int i = kNumberOfRegisters - 1; i >= 0; i--) {
int offset =

View File

@ -587,7 +587,7 @@ void Generate_JSEntryVariant(MacroAssembler* masm, StackFrame::Type type,
// a1: microtask_queue
// Save callee saved registers on the stack.
__ MultiPush(kCalleeSaved | ra.bit());
__ MultiPush(kCalleeSaved | ra);
// Save callee-saved FPU registers.
__ MultiPushFPU(kCalleeSavedFPU);
@ -743,7 +743,7 @@ void Generate_JSEntryVariant(MacroAssembler* masm, StackFrame::Type type,
__ MultiPopFPU(kCalleeSavedFPU);
// Restore callee saved registers from the stack.
__ MultiPop(kCalleeSaved | ra.bit());
__ MultiPop(kCalleeSaved | ra);
// Return.
__ Jump(ra);
}
@ -1121,7 +1121,7 @@ static void MaybeOptimizeCodeOrTailCallOptimizedCodeSlot(
// static
void Builtins::Generate_BaselineOutOfLinePrologue(MacroAssembler* masm) {
UseScratchRegisterScope temps(masm);
temps.Include(kScratchReg.bit() | kScratchReg2.bit());
temps.Include({kScratchReg, kScratchReg2});
auto descriptor =
Builtins::CallInterfaceDescriptorFor(Builtin::kBaselineOutOfLinePrologue);
Register closure = descriptor.GetRegisterParameter(
@ -1255,7 +1255,7 @@ void Builtins::Generate_BaselineOutOfLinePrologue(MacroAssembler* masm) {
__ Pop(kJavaScriptCallNewTargetRegister);
}
__ Ret();
temps.Exclude(kScratchReg.bit() | kScratchReg2.bit());
temps.Exclude({kScratchReg, kScratchReg2});
}
// Generate code for entering a JS function with the interpreter.
@ -2766,28 +2766,28 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
// Save all parameter registers (see kGpParamRegisters in wasm-linkage.cc).
// They might be overwritten in the runtime call below. We don't have any
// callee-saved registers in wasm, so no need to store anything else.
RegList gp_regs = 0;
RegList gp_regs;
for (Register gp_param_reg : wasm::kGpParamRegisters) {
gp_regs |= gp_param_reg.bit();
gp_regs.set(gp_param_reg);
}
// Also push a1, because we must push multiples of 16 bytes (see
// {TurboAssembler::PushCPURegList}.
CHECK_EQ(1, NumRegs(gp_regs) % 2);
gp_regs |= a1.bit();
CHECK_EQ(1, gp_regs.Count() % 2);
gp_regs.set(a1);
// Ensure that A1 will not be repeated.
CHECK_EQ(0, NumRegs(gp_regs) % 2);
CHECK_EQ(0, gp_regs.Count() % 2);
RegList fp_regs = 0;
RegList fp_regs;
for (DoubleRegister fp_param_reg : wasm::kFpParamRegisters) {
fp_regs |= fp_param_reg.bit();
fp_regs.set(fp_param_reg);
}
CHECK_EQ(NumRegs(gp_regs), arraysize(wasm::kGpParamRegisters) + 1);
CHECK_EQ(NumRegs(fp_regs), arraysize(wasm::kFpParamRegisters));
CHECK_EQ(gp_regs.Count(), arraysize(wasm::kGpParamRegisters) + 1);
CHECK_EQ(fp_regs.Count(), arraysize(wasm::kFpParamRegisters));
CHECK_EQ(WasmCompileLazyFrameConstants::kNumberOfSavedGpParamRegs,
NumRegs(gp_regs));
gp_regs.Count());
CHECK_EQ(WasmCompileLazyFrameConstants::kNumberOfSavedFpParamRegs,
NumRegs(fp_regs));
fp_regs.Count());
__ MultiPush(gp_regs);
__ MultiPushFPU(fp_regs);
@ -3486,7 +3486,7 @@ void Generate_DeoptimizationEntry(MacroAssembler* masm,
const int kNumberOfRegisters = Register::kNumRegisters;
RegList restored_regs = kJSCallerSaved | kCalleeSaved;
RegList saved_regs = restored_regs | sp.bit() | ra.bit();
RegList saved_regs = restored_regs | sp | ra;
const int kDoubleRegsSize = kDoubleSize * DoubleRegister::kNumRegisters;
@ -3651,7 +3651,7 @@ void Generate_DeoptimizationEntry(MacroAssembler* masm,
// Technically restoring 't3' should work unless zero_reg is also restored
// but it's safer to check for this.
DCHECK(!(t3.bit() & restored_regs));
DCHECK(!(restored_regs.has(t3)));
// Restore the registers from the last output frame.
__ Move(t3, a2);
for (int i = kNumberOfRegisters - 1; i >= 0; i--) {

View File

@ -2899,22 +2899,22 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
// Save all parameter registers (see wasm-linkage.h). They might be
// overwritten in the runtime call below. We don't have any callee-saved
// registers in wasm, so no need to store anything else.
RegList gp_regs = 0;
RegList gp_regs;
for (Register gp_param_reg : wasm::kGpParamRegisters) {
gp_regs |= gp_param_reg.bit();
gp_regs.set(gp_param_reg);
}
RegList fp_regs = 0;
RegList fp_regs;
for (DoubleRegister fp_param_reg : wasm::kFpParamRegisters) {
fp_regs |= fp_param_reg.bit();
fp_regs.set(fp_param_reg);
}
CHECK_EQ(NumRegs(gp_regs), arraysize(wasm::kGpParamRegisters));
CHECK_EQ(NumRegs(fp_regs), arraysize(wasm::kFpParamRegisters));
CHECK_EQ(gp_regs.Count(), arraysize(wasm::kGpParamRegisters));
CHECK_EQ(fp_regs.Count(), arraysize(wasm::kFpParamRegisters));
CHECK_EQ(WasmCompileLazyFrameConstants::kNumberOfSavedGpParamRegs,
NumRegs(gp_regs));
gp_regs.Count());
CHECK_EQ(WasmCompileLazyFrameConstants::kNumberOfSavedFpParamRegs,
NumRegs(fp_regs));
fp_regs.Count());
__ MultiPush(gp_regs);
__ MultiPushF64OrV128(fp_regs);

View File

@ -2845,19 +2845,19 @@ void Builtins::Generate_WasmDebugBreak(MacroAssembler* masm) {
// Save all parameter registers. They might hold live values, we restore
// them after the runtime call.
for (int reg_code : base::bits::IterateBitsBackwards(
WasmDebugBreakFrameConstants::kPushedGpRegs)) {
__ Push(Register::from_code(reg_code));
for (Register reg :
base::Reversed(WasmDebugBreakFrameConstants::kPushedGpRegs)) {
__ Push(reg);
}
constexpr int kFpStackSize =
kSimd128Size * WasmDebugBreakFrameConstants::kNumPushedFpRegisters;
__ AllocateStackSpace(kFpStackSize);
int offset = kFpStackSize;
for (int reg_code : base::bits::IterateBitsBackwards(
WasmDebugBreakFrameConstants::kPushedFpRegs)) {
for (DoubleRegister reg :
base::Reversed(WasmDebugBreakFrameConstants::kPushedFpRegs)) {
offset -= kSimd128Size;
__ movdqu(Operand(rsp, offset), DoubleRegister::from_code(reg_code));
__ movdqu(Operand(rsp, offset), reg);
}
// Initialize the JavaScript context with 0. CEntry will use it to
@ -2866,15 +2866,13 @@ void Builtins::Generate_WasmDebugBreak(MacroAssembler* masm) {
__ CallRuntime(Runtime::kWasmDebugBreak, 0);
// Restore registers.
for (int reg_code :
base::bits::IterateBits(WasmDebugBreakFrameConstants::kPushedFpRegs)) {
__ movdqu(DoubleRegister::from_code(reg_code), Operand(rsp, offset));
for (DoubleRegister reg : WasmDebugBreakFrameConstants::kPushedFpRegs) {
__ movdqu(reg, Operand(rsp, offset));
offset += kSimd128Size;
}
__ addq(rsp, Immediate(kFpStackSize));
for (int reg_code :
base::bits::IterateBits(WasmDebugBreakFrameConstants::kPushedGpRegs)) {
__ Pop(Register::from_code(reg_code));
for (Register reg : WasmDebugBreakFrameConstants::kPushedGpRegs) {
__ Pop(reg);
}
}

View File

@ -533,7 +533,7 @@ Assembler::Assembler(const AssemblerOptions& options,
std::unique_ptr<AssemblerBuffer> buffer)
: AssemblerBase(options, std::move(buffer)),
pending_32_bit_constants_(),
scratch_register_list_(ip.bit()) {
scratch_register_list_({ip}) {
reloc_info_writer.Reposition(buffer_start_ + buffer_->size(), pc_);
constant_pool_deadline_ = kMaxInt;
const_pool_blocked_nesting_ = 0;
@ -1412,9 +1412,9 @@ void Assembler::AddrMode3(Instr instr, Register rd, const MemOperand& x) {
void Assembler::AddrMode4(Instr instr, Register rn, RegList rl) {
DCHECK((instr & ~(kCondMask | P | U | W | L)) == B27);
DCHECK_NE(rl, 0);
DCHECK(!rl.is_empty());
DCHECK(rn != pc);
emit(instr | rn.code() * B16 | rl);
emit(instr | rn.code() * B16 | rl.bits());
}
void Assembler::AddrMode5(Instr instr, CRegister crd, const MemOperand& x) {
@ -2251,12 +2251,12 @@ void Assembler::pld(const MemOperand& address) {
void Assembler::ldm(BlockAddrMode am, Register base, RegList dst,
Condition cond) {
// ABI stack constraint: ldmxx base, {..sp..} base != sp is not restartable.
DCHECK(base == sp || (dst & sp.bit()) == 0);
DCHECK(base == sp || !dst.has(sp));
AddrMode4(cond | B27 | am | L, base, dst);
// Emit the constant pool after a function return implemented by ldm ..{..pc}.
if (cond == al && (dst & pc.bit()) != 0) {
if (cond == al && dst.has(pc)) {
// There is a slight chance that the ldm instruction was actually a call,
// in which case it would be wrong to return into the constant pool; we
// recognize this case by checking if the emission of the pool was blocked
@ -5499,11 +5499,7 @@ UseScratchRegisterScope::~UseScratchRegisterScope() {
Register UseScratchRegisterScope::Acquire() {
RegList* available = assembler_->GetScratchRegisterList();
DCHECK_NOT_NULL(available);
DCHECK_NE(*available, 0);
int index = static_cast<int>(base::bits::CountTrailingZeros32(*available));
Register reg = Register::from_code(index);
*available &= ~reg.bit();
return reg;
return available->PopFirst();
}
LoadStoreLaneParams::LoadStoreLaneParams(MachineRepresentation rep,

View File

@ -1399,21 +1399,25 @@ class V8_EXPORT_PRIVATE V8_NODISCARD UseScratchRegisterScope {
}
// Check if we have registers available to acquire.
bool CanAcquire() const { return *assembler_->GetScratchRegisterList() != 0; }
bool CanAcquire() const {
return !assembler_->GetScratchRegisterList()->is_empty();
}
bool CanAcquireD() const { return CanAcquireVfp<DwVfpRegister>(); }
void Include(const Register& reg1, const Register& reg2 = no_reg) {
RegList* available = assembler_->GetScratchRegisterList();
DCHECK_NOT_NULL(available);
DCHECK_EQ((*available) & (reg1.bit() | reg2.bit()), 0);
*available |= reg1.bit() | reg2.bit();
DCHECK(!available->has(reg1));
DCHECK(!available->has(reg2));
available->set(reg1);
available->set(reg2);
}
void Exclude(const Register& reg1, const Register& reg2 = no_reg) {
RegList* available = assembler_->GetScratchRegisterList();
DCHECK_NOT_NULL(available);
DCHECK_EQ((*available) & (reg1.bit() | reg2.bit()),
reg1.bit() | reg2.bit());
*available &= ~(reg1.bit() | reg2.bit());
DCHECK(available->has(reg1));
DCHECK_IMPLIES(reg2.is_valid(), available->has(reg2));
available->clear(RegList{reg1, reg2});
}
private:

View File

@ -24,21 +24,21 @@ template <typename DerivedDescriptor>
void StaticCallInterfaceDescriptor<DerivedDescriptor>::
VerifyArgumentRegisterCount(CallInterfaceDescriptorData* data, int argc) {
RegList allocatable_regs = data->allocatable_registers();
if (argc >= 1) DCHECK(allocatable_regs | r0.bit());
if (argc >= 2) DCHECK(allocatable_regs | r1.bit());
if (argc >= 3) DCHECK(allocatable_regs | r2.bit());
if (argc >= 4) DCHECK(allocatable_regs | r3.bit());
if (argc >= 5) DCHECK(allocatable_regs | r4.bit());
if (argc >= 6) DCHECK(allocatable_regs | r5.bit());
if (argc >= 7) DCHECK(allocatable_regs | r6.bit());
if (argc >= 8) DCHECK(allocatable_regs | r7.bit());
if (argc >= 1) DCHECK(allocatable_regs.has(r0));
if (argc >= 2) DCHECK(allocatable_regs.has(r1));
if (argc >= 3) DCHECK(allocatable_regs.has(r2));
if (argc >= 4) DCHECK(allocatable_regs.has(r3));
if (argc >= 5) DCHECK(allocatable_regs.has(r4));
if (argc >= 6) DCHECK(allocatable_regs.has(r5));
if (argc >= 7) DCHECK(allocatable_regs.has(r6));
if (argc >= 8) DCHECK(allocatable_regs.has(r7));
// Additional arguments are passed on the stack.
}
#endif // DEBUG
// static
constexpr auto WriteBarrierDescriptor::registers() {
return RegisterArray(r1, r5, r4, r2, r0);
return RegisterArray(r1, r5, r4, r2, r0, r3, kContextRegister);
}
// static

View File

@ -45,20 +45,10 @@ int TurboAssembler::RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode,
Register exclusion2,
Register exclusion3) const {
int bytes = 0;
RegList exclusions = 0;
if (exclusion1 != no_reg) {
exclusions |= exclusion1.bit();
if (exclusion2 != no_reg) {
exclusions |= exclusion2.bit();
if (exclusion3 != no_reg) {
exclusions |= exclusion3.bit();
}
}
}
RegList exclusions = {exclusion1, exclusion2, exclusion3};
RegList list = (kCallerSaved | lr) - exclusions;
RegList list = (kCallerSaved | lr.bit()) & ~exclusions;
bytes += NumRegs(list) * kPointerSize;
bytes += list.Count() * kPointerSize;
if (fp_mode == SaveFPRegsMode::kSave) {
bytes += DwVfpRegister::kNumRegisters * DwVfpRegister::kSizeInBytes;
@ -71,21 +61,11 @@ int TurboAssembler::PushCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
Register exclusion2, Register exclusion3) {
ASM_CODE_COMMENT(this);
int bytes = 0;
RegList exclusions = 0;
if (exclusion1 != no_reg) {
exclusions |= exclusion1.bit();
if (exclusion2 != no_reg) {
exclusions |= exclusion2.bit();
if (exclusion3 != no_reg) {
exclusions |= exclusion3.bit();
}
}
}
RegList list = (kCallerSaved | lr.bit()) & ~exclusions;
RegList exclusions = {exclusion1, exclusion2, exclusion3};
RegList list = (kCallerSaved | lr) - exclusions;
stm(db_w, sp, list);
bytes += NumRegs(list) * kPointerSize;
bytes += list.Count() * kPointerSize;
if (fp_mode == SaveFPRegsMode::kSave) {
SaveFPRegs(sp, lr);
@ -104,21 +84,11 @@ int TurboAssembler::PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
bytes += DwVfpRegister::kNumRegisters * DwVfpRegister::kSizeInBytes;
}
RegList exclusions = 0;
if (exclusion1 != no_reg) {
exclusions |= exclusion1.bit();
if (exclusion2 != no_reg) {
exclusions |= exclusion2.bit();
if (exclusion3 != no_reg) {
exclusions |= exclusion3.bit();
}
}
}
RegList list = (kCallerSaved | lr.bit()) & ~exclusions;
RegList exclusions = {exclusion1, exclusion2, exclusion3};
RegList list = (kCallerSaved | lr) - exclusions;
ldm(ia_w, sp, list);
bytes += NumRegs(list) * kPointerSize;
bytes += list.Count() * kPointerSize;
return bytes;
}
@ -696,27 +666,15 @@ void MacroAssembler::RecordWriteField(Register object, int offset,
}
void TurboAssembler::MaybeSaveRegisters(RegList registers) {
if (registers == 0) return;
if (registers.is_empty()) return;
ASM_CODE_COMMENT(this);
RegList regs = 0;
for (int i = 0; i < Register::kNumRegisters; ++i) {
if ((registers >> i) & 1u) {
regs |= Register::from_code(i).bit();
}
}
stm(db_w, sp, regs);
stm(db_w, sp, registers);
}
void TurboAssembler::MaybeRestoreRegisters(RegList registers) {
if (registers == 0) return;
if (registers.is_empty()) return;
ASM_CODE_COMMENT(this);
RegList regs = 0;
for (int i = 0; i < Register::kNumRegisters; ++i) {
if ((registers >> i) & 1u) {
regs |= Register::from_code(i).bit();
}
}
ldm(ia_w, sp, regs);
ldm(ia_w, sp, registers);
}
void TurboAssembler::CallEphemeronKeyBarrier(Register object, Operand offset,
@ -876,15 +834,15 @@ void TurboAssembler::PushCommonFrame(Register marker_reg) {
ASM_CODE_COMMENT(this);
if (marker_reg.is_valid()) {
if (marker_reg.code() > fp.code()) {
stm(db_w, sp, fp.bit() | lr.bit());
stm(db_w, sp, {fp, lr});
mov(fp, Operand(sp));
Push(marker_reg);
} else {
stm(db_w, sp, marker_reg.bit() | fp.bit() | lr.bit());
stm(db_w, sp, {marker_reg, fp, lr});
add(fp, sp, Operand(kPointerSize));
}
} else {
stm(db_w, sp, fp.bit() | lr.bit());
stm(db_w, sp, {fp, lr});
mov(fp, sp);
}
}
@ -892,9 +850,7 @@ void TurboAssembler::PushCommonFrame(Register marker_reg) {
void TurboAssembler::PushStandardFrame(Register function_reg) {
ASM_CODE_COMMENT(this);
DCHECK(!function_reg.is_valid() || function_reg.code() < cp.code());
stm(db_w, sp,
(function_reg.is_valid() ? function_reg.bit() : 0) | cp.bit() | fp.bit() |
lr.bit());
stm(db_w, sp, {function_reg, cp, fp, lr});
int offset = -StandardFrameConstants::kContextOffset;
offset += function_reg.is_valid() ? kPointerSize : 0;
add(fp, sp, Operand(offset));
@ -1426,7 +1382,7 @@ int TurboAssembler::LeaveFrame(StackFrame::Type type) {
// the caller frame pointer and return address.
mov(sp, fp);
int frame_ends = pc_offset();
ldm(ia_w, sp, fp.bit() | lr.bit());
ldm(ia_w, sp, {fp, lr});
return frame_ends;
}
@ -1575,7 +1531,7 @@ void MacroAssembler::LeaveExitFrame(bool save_doubles, Register argument_count,
// Tear down the exit frame, pop the arguments, and return.
mov(sp, Operand(fp));
ldm(ia_w, sp, fp.bit() | lr.bit());
ldm(ia_w, sp, {fp, lr});
if (argument_count.is_valid()) {
if (argument_count_is_length) {
add(sp, sp, argument_count);
@ -2659,19 +2615,13 @@ void TurboAssembler::CheckPageFlag(Register object, int mask, Condition cc,
Register GetRegisterThatIsNotOneOf(Register reg1, Register reg2, Register reg3,
Register reg4, Register reg5,
Register reg6) {
RegList regs = 0;
if (reg1.is_valid()) regs |= reg1.bit();
if (reg2.is_valid()) regs |= reg2.bit();
if (reg3.is_valid()) regs |= reg3.bit();
if (reg4.is_valid()) regs |= reg4.bit();
if (reg5.is_valid()) regs |= reg5.bit();
if (reg6.is_valid()) regs |= reg6.bit();
RegList regs = {reg1, reg2, reg3, reg4, reg5, reg6};
const RegisterConfiguration* config = RegisterConfiguration::Default();
for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
int code = config->GetAllocatableGeneralCode(i);
Register candidate = Register::from_code(code);
if (regs & candidate.bit()) continue;
if (regs.has(candidate)) continue;
return candidate;
}
UNREACHABLE();

View File

@ -97,7 +97,7 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
// Push two registers. Pushes leftmost register first (to highest address).
void Push(Register src1, Register src2, Condition cond = al) {
if (src1.code() > src2.code()) {
stm(db_w, sp, src1.bit() | src2.bit(), cond);
stm(db_w, sp, {src1, src2}, cond);
} else {
str(src1, MemOperand(sp, 4, NegPreIndex), cond);
str(src2, MemOperand(sp, 4, NegPreIndex), cond);
@ -108,9 +108,9 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
void Push(Register src1, Register src2, Register src3, Condition cond = al) {
if (src1.code() > src2.code()) {
if (src2.code() > src3.code()) {
stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
stm(db_w, sp, {src1, src2, src3}, cond);
} else {
stm(db_w, sp, src1.bit() | src2.bit(), cond);
stm(db_w, sp, {src1, src2}, cond);
str(src3, MemOperand(sp, 4, NegPreIndex), cond);
}
} else {
@ -125,14 +125,13 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
if (src1.code() > src2.code()) {
if (src2.code() > src3.code()) {
if (src3.code() > src4.code()) {
stm(db_w, sp, src1.bit() | src2.bit() | src3.bit() | src4.bit(),
cond);
stm(db_w, sp, {src1, src2, src3, src4}, cond);
} else {
stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
stm(db_w, sp, {src1, src2, src3}, cond);
str(src4, MemOperand(sp, 4, NegPreIndex), cond);
}
} else {
stm(db_w, sp, src1.bit() | src2.bit(), cond);
stm(db_w, sp, {src1, src2}, cond);
Push(src3, src4, cond);
}
} else {
@ -148,20 +147,17 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
if (src2.code() > src3.code()) {
if (src3.code() > src4.code()) {
if (src4.code() > src5.code()) {
stm(db_w, sp,
src1.bit() | src2.bit() | src3.bit() | src4.bit() | src5.bit(),
cond);
stm(db_w, sp, {src1, src2, src3, src4, src5}, cond);
} else {
stm(db_w, sp, src1.bit() | src2.bit() | src3.bit() | src4.bit(),
cond);
stm(db_w, sp, {src1, src2, src3, src4}, cond);
str(src5, MemOperand(sp, 4, NegPreIndex), cond);
}
} else {
stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
stm(db_w, sp, {src1, src2, src3}, cond);
Push(src4, src5, cond);
}
} else {
stm(db_w, sp, src1.bit() | src2.bit(), cond);
stm(db_w, sp, {src1, src2}, cond);
Push(src3, src4, src5, cond);
}
} else {
@ -182,7 +178,7 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
void Pop(Register src1, Register src2, Condition cond = al) {
DCHECK(src1 != src2);
if (src1.code() > src2.code()) {
ldm(ia_w, sp, src1.bit() | src2.bit(), cond);
ldm(ia_w, sp, {src1, src2}, cond);
} else {
ldr(src2, MemOperand(sp, 4, PostIndex), cond);
ldr(src1, MemOperand(sp, 4, PostIndex), cond);
@ -194,10 +190,10 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
DCHECK(!AreAliased(src1, src2, src3));
if (src1.code() > src2.code()) {
if (src2.code() > src3.code()) {
ldm(ia_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
ldm(ia_w, sp, {src1, src2, src3}, cond);
} else {
ldr(src3, MemOperand(sp, 4, PostIndex), cond);
ldm(ia_w, sp, src1.bit() | src2.bit(), cond);
ldm(ia_w, sp, {src1, src2}, cond);
}
} else {
Pop(src2, src3, cond);
@ -212,15 +208,14 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
if (src1.code() > src2.code()) {
if (src2.code() > src3.code()) {
if (src3.code() > src4.code()) {
ldm(ia_w, sp, src1.bit() | src2.bit() | src3.bit() | src4.bit(),
cond);
ldm(ia_w, sp, {src1, src2, src3, src4}, cond);
} else {
ldr(src4, MemOperand(sp, 4, PostIndex), cond);
ldm(ia_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
ldm(ia_w, sp, {src1, src2, src3}, cond);
}
} else {
Pop(src3, src4, cond);
ldm(ia_w, sp, src1.bit() | src2.bit(), cond);
ldm(ia_w, sp, {src1, src2}, cond);
}
} else {
Pop(src2, src3, src4, cond);

View File

@ -6,8 +6,6 @@
#define V8_CODEGEN_ARM_REGISTER_ARM_H_
#include "src/codegen/register-base.h"
#include "src/codegen/register-configuration.h"
#include "src/codegen/reglist.h"
namespace v8 {
namespace internal {
@ -62,40 +60,6 @@ namespace internal {
// leave it alone. Adjust the value of kR9Available accordingly:
const int kR9Available = 1; // 1 if available to us, 0 if reserved
// Register list in load/store instructions
// Note that the bit values must match those used in actual instruction encoding
// Caller-saved/arguments registers
const RegList kJSCallerSaved = 1 << 0 | // r0 a1
1 << 1 | // r1 a2
1 << 2 | // r2 a3
1 << 3; // r3 a4
const int kNumJSCallerSaved = 4;
// Callee-saved registers preserved when switching from C to JavaScript
const RegList kCalleeSaved = 1 << 4 | // r4 v1
1 << 5 | // r5 v2
1 << 6 | // r6 v3
1 << 7 | // r7 v4 (cp in JavaScript code)
1 << 8 | // r8 v5 (pp in JavaScript code)
kR9Available << 9 | // r9 v6
1 << 10 | // r10 v7
1 << 11; // r11 v8 (fp in JavaScript code)
// When calling into C++ (only for C++ calls that can't cause a GC).
// The call code will take care of lr, fp, etc.
const RegList kCallerSaved = 1 << 0 | // r0
1 << 1 | // r1
1 << 2 | // r2
1 << 3 | // r3
1 << 9; // r9
const int kNumCalleeSaved = 7 + kR9Available;
// Double registers d8 to d15 are callee-saved.
const int kNumDoubleCalleeSaved = 8;
enum RegisterCode {
#define REGISTER_CODE(R) kRegCode_##R,
GENERAL_REGISTERS(REGISTER_CODE)
@ -357,6 +321,7 @@ constexpr Register kWasmCompileLazyFuncIndexRegister = r4;
// Give alias names to registers
constexpr Register cp = r7; // JavaScript context pointer.
constexpr Register r11 = fp;
constexpr Register kRootRegister = r10; // Roots array pointer.
constexpr DoubleRegister kFPReturnRegister0 = d0;

View File

@ -0,0 +1,56 @@
// Copyright 2022 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_ARM_REGLIST_ARM_H_
#define V8_CODEGEN_ARM_REGLIST_ARM_H_
#include "src/codegen/register-arch.h"
#include "src/codegen/reglist-base.h"
namespace v8 {
namespace internal {
using RegList = RegListBase<Register>;
using DoubleRegList = RegListBase<DoubleRegister>;
ASSERT_TRIVIALLY_COPYABLE(RegList);
ASSERT_TRIVIALLY_COPYABLE(DoubleRegList);
// Register list in load/store instructions
// Note that the bit values must match those used in actual instruction encoding
// Caller-saved/arguments registers
const RegList kJSCallerSaved = {r0, // r0 a1
r1, // r1 a2
r2, // r2 a3
r3}; // r3 a4
const int kNumJSCallerSaved = 4;
// Callee-saved registers preserved when switching from C to JavaScript
const RegList kCalleeSaved = {r4, // r4 v1
r5, // r5 v2
r6, // r6 v3
r7, // r7 v4 (cp in JavaScript code)
r8, // r8 v5 (pp in JavaScript code)
kR9Available ? r9 : Register::no_reg(), // r9 v6
r10, // r10 v7
r11}; // r11 v8 (fp in JavaScript code)
// When calling into C++ (only for C++ calls that can't cause a GC).
// The call code will take care of lr, fp, etc.
const RegList kCallerSaved = {r0, // r0
r1, // r1
r2, // r2
r3, // r3
r9}; // r9
const int kNumCalleeSaved = 7 + kR9Available;
// Double registers d8 to d15 are callee-saved.
const int kNumDoubleCalleeSaved = 8;
} // namespace internal
} // namespace v8
#endif // V8_CODEGEN_ARM_REGLIST_ARM_H_

View File

@ -54,12 +54,12 @@ inline bool CPURegister::IsSP() const {
inline void CPURegList::Combine(const CPURegList& other) {
DCHECK(other.type() == type_);
DCHECK(other.RegisterSizeInBits() == size_);
list_ |= other.list();
list_ |= other.list_;
}
inline void CPURegList::Remove(const CPURegList& other) {
if (other.type() == type_) {
list_ &= ~other.list();
list_ &= ~other.list_;
}
}

View File

@ -228,18 +228,18 @@ bool AreAliased(const CPURegister& reg1, const CPURegister& reg2,
int number_of_valid_regs = 0;
int number_of_valid_fpregs = 0;
RegList unique_regs = 0;
RegList unique_fpregs = 0;
uint64_t unique_regs = 0;
uint64_t unique_fpregs = 0;
const CPURegister regs[] = {reg1, reg2, reg3, reg4, reg5, reg6, reg7, reg8};
for (unsigned i = 0; i < arraysize(regs); i++) {
if (regs[i].IsRegister()) {
number_of_valid_regs++;
unique_regs |= regs[i].bit();
unique_regs |= (uint64_t{1} << regs[i].code());
} else if (regs[i].IsVRegister()) {
number_of_valid_fpregs++;
unique_fpregs |= regs[i].bit();
unique_fpregs |= (uint64_t{1} << regs[i].code());
} else {
DCHECK(!regs[i].is_valid());
}

View File

@ -25,20 +25,21 @@ template <typename DerivedDescriptor>
void StaticCallInterfaceDescriptor<DerivedDescriptor>::
VerifyArgumentRegisterCount(CallInterfaceDescriptorData* data, int argc) {
RegList allocatable_regs = data->allocatable_registers();
if (argc >= 1) DCHECK(allocatable_regs | x0.bit());
if (argc >= 2) DCHECK(allocatable_regs | x1.bit());
if (argc >= 3) DCHECK(allocatable_regs | x2.bit());
if (argc >= 4) DCHECK(allocatable_regs | x3.bit());
if (argc >= 5) DCHECK(allocatable_regs | x4.bit());
if (argc >= 6) DCHECK(allocatable_regs | x5.bit());
if (argc >= 7) DCHECK(allocatable_regs | x6.bit());
if (argc >= 8) DCHECK(allocatable_regs | x7.bit());
if (argc >= 1) DCHECK(allocatable_regs.has(x0));
if (argc >= 2) DCHECK(allocatable_regs.has(x1));
if (argc >= 3) DCHECK(allocatable_regs.has(x2));
if (argc >= 4) DCHECK(allocatable_regs.has(x3));
if (argc >= 5) DCHECK(allocatable_regs.has(x4));
if (argc >= 6) DCHECK(allocatable_regs.has(x5));
if (argc >= 7) DCHECK(allocatable_regs.has(x6));
if (argc >= 8) DCHECK(allocatable_regs.has(x7));
}
#endif // DEBUG
// static
constexpr auto WriteBarrierDescriptor::registers() {
return RegisterArray(x1, x5, x4, x2, x0, x3);
// TODO(leszeks): Remove x7 which is just there for padding.
return RegisterArray(x1, x5, x4, x2, x0, x3, kContextRegister, x7);
}
// static

View File

@ -3134,9 +3134,9 @@ void TurboAssembler::LoadExternalPointerField(Register destination,
}
void TurboAssembler::MaybeSaveRegisters(RegList registers) {
if (registers == 0) return;
if (registers.is_empty()) return;
ASM_CODE_COMMENT(this);
CPURegList regs(CPURegister::kRegister, kXRegSizeInBits, registers);
CPURegList regs(kXRegSizeInBits, registers);
// If we were saving LR, we might need to sign it.
DCHECK(!regs.IncludesAliasOf(lr));
regs.Align();
@ -3144,9 +3144,9 @@ void TurboAssembler::MaybeSaveRegisters(RegList registers) {
}
void TurboAssembler::MaybeRestoreRegisters(RegList registers) {
if (registers == 0) return;
if (registers.is_empty()) return;
ASM_CODE_COMMENT(this);
CPURegList regs(CPURegister::kRegister, kXRegSizeInBits, registers);
CPURegList regs(kXRegSizeInBits, registers);
// If we were saving LR, we might need to sign it.
DCHECK(!regs.IncludesAliasOf(lr));
regs.Align();
@ -3346,7 +3346,7 @@ void TurboAssembler::Abort(AbortReason reason) {
// We need some scratch registers for the MacroAssembler, so make sure we have
// some. This is safe here because Abort never returns.
RegList old_tmp_list = TmpList()->list();
uint64_t old_tmp_list = TmpList()->bits();
TmpList()->Combine(MacroAssembler::DefaultTmpList());
if (should_abort_hard()) {
@ -3371,7 +3371,7 @@ void TurboAssembler::Abort(AbortReason reason) {
Call(BUILTIN_CODE(isolate(), Abort), RelocInfo::CODE_TARGET);
}
TmpList()->set_list(old_tmp_list);
TmpList()->set_bits(old_tmp_list);
}
void MacroAssembler::LoadNativeContextSlot(Register dst, int index) {
@ -3421,8 +3421,8 @@ void TurboAssembler::PrintfNoPreserve(const char* format,
// Override the TurboAssembler's scratch register list. The lists will be
// reset automatically at the end of the UseScratchRegisterScope.
UseScratchRegisterScope temps(this);
TmpList()->set_list(tmp_list.list());
FPTmpList()->set_list(fp_tmp_list.list());
TmpList()->set_bits(tmp_list.bits());
FPTmpList()->set_bits(fp_tmp_list.bits());
// Copies of the printf vararg registers that we can pop from.
CPURegList pcs_varargs = kPCSVarargs;
@ -3570,10 +3570,10 @@ void TurboAssembler::Printf(const char* format, CPURegister arg0,
ASM_CODE_COMMENT(this);
// Printf is expected to preserve all registers, so make sure that none are
// available as scratch registers until we've preserved them.
RegList old_tmp_list = TmpList()->list();
RegList old_fp_tmp_list = FPTmpList()->list();
TmpList()->set_list(0);
FPTmpList()->set_list(0);
uint64_t old_tmp_list = TmpList()->bits();
uint64_t old_fp_tmp_list = FPTmpList()->bits();
TmpList()->set_bits(0);
FPTmpList()->set_bits(0);
CPURegList saved_registers = kCallerSaved;
saved_registers.Align();
@ -3589,8 +3589,8 @@ void TurboAssembler::Printf(const char* format, CPURegister arg0,
CPURegList fp_tmp_list = kCallerSavedV;
tmp_list.Remove(arg0, arg1, arg2, arg3);
fp_tmp_list.Remove(arg0, arg1, arg2, arg3);
TmpList()->set_list(tmp_list.list());
FPTmpList()->set_list(fp_tmp_list.list());
TmpList()->set_bits(tmp_list.bits());
FPTmpList()->set_bits(fp_tmp_list.bits());
{
UseScratchRegisterScope temps(this);
@ -3636,13 +3636,13 @@ void TurboAssembler::Printf(const char* format, CPURegister arg0,
PopCPURegList(kCallerSavedV);
PopCPURegList<kDontLoadLR>(saved_registers);
TmpList()->set_list(old_tmp_list);
FPTmpList()->set_list(old_fp_tmp_list);
TmpList()->set_bits(old_tmp_list);
FPTmpList()->set_bits(old_fp_tmp_list);
}
UseScratchRegisterScope::~UseScratchRegisterScope() {
available_->set_list(old_available_);
availablefp_->set_list(old_availablefp_);
available_->set_bits(old_available_);
availablefp_->set_bits(old_availablefp_);
}
Register UseScratchRegisterScope::AcquireSameSizeAs(const Register& reg) {

View File

@ -1755,16 +1755,20 @@ class V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler {
// For the 'lr_mode' template argument of the following methods, see
// PushCPURegList/PopCPURegList.
template <StoreLRMode lr_mode = kDontStoreLR>
inline void PushSizeRegList(
RegList registers, unsigned reg_size,
CPURegister::RegisterType type = CPURegister::kRegister) {
PushCPURegList<lr_mode>(CPURegList(type, reg_size, registers));
inline void PushSizeRegList(RegList registers, unsigned reg_size) {
PushCPURegList<lr_mode>(CPURegList(reg_size, registers));
}
template <StoreLRMode lr_mode = kDontStoreLR>
inline void PushSizeRegList(DoubleRegList registers, unsigned reg_size) {
PushCPURegList<lr_mode>(CPURegList(reg_size, registers));
}
template <LoadLRMode lr_mode = kDontLoadLR>
inline void PopSizeRegList(
RegList registers, unsigned reg_size,
CPURegister::RegisterType type = CPURegister::kRegister) {
PopCPURegList<lr_mode>(CPURegList(type, reg_size, registers));
inline void PopSizeRegList(RegList registers, unsigned reg_size) {
PopCPURegList<lr_mode>(CPURegList(reg_size, registers));
}
template <LoadLRMode lr_mode = kDontLoadLR>
inline void PopSizeRegList(DoubleRegList registers, unsigned reg_size) {
PopCPURegList<lr_mode>(CPURegList(reg_size, registers));
}
template <StoreLRMode lr_mode = kDontStoreLR>
inline void PushXRegList(RegList regs) {
@ -1780,23 +1784,23 @@ class V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler {
inline void PopWRegList(RegList regs) {
PopSizeRegList(regs, kWRegSizeInBits);
}
inline void PushQRegList(RegList regs) {
PushSizeRegList(regs, kQRegSizeInBits, CPURegister::kVRegister);
inline void PushQRegList(DoubleRegList regs) {
PushSizeRegList(regs, kQRegSizeInBits);
}
inline void PopQRegList(RegList regs) {
PopSizeRegList(regs, kQRegSizeInBits, CPURegister::kVRegister);
inline void PopQRegList(DoubleRegList regs) {
PopSizeRegList(regs, kQRegSizeInBits);
}
inline void PushDRegList(RegList regs) {
PushSizeRegList(regs, kDRegSizeInBits, CPURegister::kVRegister);
inline void PushDRegList(DoubleRegList regs) {
PushSizeRegList(regs, kDRegSizeInBits);
}
inline void PopDRegList(RegList regs) {
PopSizeRegList(regs, kDRegSizeInBits, CPURegister::kVRegister);
inline void PopDRegList(DoubleRegList regs) {
PopSizeRegList(regs, kDRegSizeInBits);
}
inline void PushSRegList(RegList regs) {
PushSizeRegList(regs, kSRegSizeInBits, CPURegister::kVRegister);
inline void PushSRegList(DoubleRegList regs) {
PushSizeRegList(regs, kSRegSizeInBits);
}
inline void PopSRegList(RegList regs) {
PopSizeRegList(regs, kSRegSizeInBits, CPURegister::kVRegister);
inline void PopSRegList(DoubleRegList regs) {
PopSizeRegList(regs, kSRegSizeInBits);
}
// Push the specified register 'count' times.
@ -2154,8 +2158,8 @@ class V8_NODISCARD UseScratchRegisterScope {
explicit UseScratchRegisterScope(TurboAssembler* tasm)
: available_(tasm->TmpList()),
availablefp_(tasm->FPTmpList()),
old_available_(available_->list()),
old_availablefp_(availablefp_->list()) {
old_available_(available_->bits()),
old_availablefp_(availablefp_->bits()) {
DCHECK_EQ(available_->type(), CPURegister::kRegister);
DCHECK_EQ(availablefp_->type(), CPURegister::kVRegister);
}
@ -2205,8 +2209,8 @@ class V8_NODISCARD UseScratchRegisterScope {
CPURegList* availablefp_; // kVRegister
// The state of the available lists at the start of this scope.
RegList old_available_; // kRegister
RegList old_availablefp_; // kVRegister
uint64_t old_available_; // kRegister
uint64_t old_availablefp_; // kVRegister
};
} // namespace internal

View File

@ -7,8 +7,6 @@
#include "src/codegen/arm64/utils-arm64.h"
#include "src/codegen/register-base.h"
#include "src/codegen/register-configuration.h"
#include "src/codegen/reglist.h"
#include "src/common/globals.h"
namespace v8 {
@ -80,8 +78,6 @@ namespace internal {
R(d25) R(d26) R(d27) R(d28)
// clang-format on
constexpr int kRegListSizeInBits = sizeof(RegList) * kBitsPerByte;
// Some CPURegister methods can return Register and VRegister types, so we
// need to declare them in advance.
class Register;
@ -244,19 +240,6 @@ class Register : public CPURegister {
return Register::Create(code, kXRegSizeInBits);
}
// Copied from RegisterBase since there's no CPURegister::from_code.
static constexpr Register FirstOf(RegList list) {
DCHECK_NE(kEmptyRegList, list);
return from_code(base::bits::CountTrailingZerosNonZero(list));
}
static constexpr Register TakeFirst(RegList* list) {
RegList value = *list;
Register result = FirstOf(value);
result.RemoveFrom(list);
return result;
}
static const char* GetSpecialRegisterName(int code) {
return (code == kSPRegInternalCode) ? "sp" : "UNKNOWN";
}
@ -563,150 +546,6 @@ using FloatRegister = VRegister;
using DoubleRegister = VRegister;
using Simd128Register = VRegister;
// -----------------------------------------------------------------------------
// Lists of registers.
class V8_EXPORT_PRIVATE CPURegList {
public:
template <typename... CPURegisters>
explicit CPURegList(CPURegister reg0, CPURegisters... regs)
: list_(CPURegister::ListOf(reg0, regs...)),
size_(reg0.SizeInBits()),
type_(reg0.type()) {
DCHECK(AreSameSizeAndType(reg0, regs...));
DCHECK(is_valid());
}
CPURegList(CPURegister::RegisterType type, int size, RegList list)
: list_(list), size_(size), type_(type) {
DCHECK(is_valid());
}
CPURegList(CPURegister::RegisterType type, int size, int first_reg,
int last_reg)
: size_(size), type_(type) {
DCHECK(
((type == CPURegister::kRegister) && (last_reg < kNumberOfRegisters)) ||
((type == CPURegister::kVRegister) &&
(last_reg < kNumberOfVRegisters)));
DCHECK(last_reg >= first_reg);
list_ = (1ULL << (last_reg + 1)) - 1;
list_ &= ~((1ULL << first_reg) - 1);
DCHECK(is_valid());
}
CPURegister::RegisterType type() const {
return type_;
}
RegList list() const {
return list_;
}
inline void set_list(RegList new_list) {
list_ = new_list;
DCHECK(is_valid());
}
// Combine another CPURegList into this one. Registers that already exist in
// this list are left unchanged. The type and size of the registers in the
// 'other' list must match those in this list.
void Combine(const CPURegList& other);
// Remove every register in the other CPURegList from this one. Registers that
// do not exist in this list are ignored. The type of the registers in the
// 'other' list must match those in this list.
void Remove(const CPURegList& other);
// Variants of Combine and Remove which take CPURegisters.
void Combine(const CPURegister& other);
void Remove(const CPURegister& other1, const CPURegister& other2 = NoCPUReg,
const CPURegister& other3 = NoCPUReg,
const CPURegister& other4 = NoCPUReg);
// Variants of Combine and Remove which take a single register by its code;
// the type and size of the register is inferred from this list.
void Combine(int code);
void Remove(int code);
// Align the list to 16 bytes.
void Align();
CPURegister PopLowestIndex();
CPURegister PopHighestIndex();
// AAPCS64 callee-saved registers.
static CPURegList GetCalleeSaved(int size = kXRegSizeInBits);
static CPURegList GetCalleeSavedV(int size = kDRegSizeInBits);
// AAPCS64 caller-saved registers. Note that this includes lr.
// TODO(all): Determine how we handle d8-d15 being callee-saved, but the top
// 64-bits being caller-saved.
static CPURegList GetCallerSaved(int size = kXRegSizeInBits);
static CPURegList GetCallerSavedV(int size = kDRegSizeInBits);
bool IsEmpty() const {
return list_ == 0;
}
bool IncludesAliasOf(const CPURegister& other1,
const CPURegister& other2 = NoCPUReg,
const CPURegister& other3 = NoCPUReg,
const CPURegister& other4 = NoCPUReg) const {
RegList list = 0;
if (!other1.IsNone() && (other1.type() == type_)) list |= other1.bit();
if (!other2.IsNone() && (other2.type() == type_)) list |= other2.bit();
if (!other3.IsNone() && (other3.type() == type_)) list |= other3.bit();
if (!other4.IsNone() && (other4.type() == type_)) list |= other4.bit();
return (list_ & list) != 0;
}
int Count() const {
return CountSetBits(list_, kRegListSizeInBits);
}
int RegisterSizeInBits() const {
return size_;
}
int RegisterSizeInBytes() const {
int size_in_bits = RegisterSizeInBits();
DCHECK_EQ(size_in_bits % kBitsPerByte, 0);
return size_in_bits / kBitsPerByte;
}
int TotalSizeInBytes() const {
return RegisterSizeInBytes() * Count();
}
private:
RegList list_;
int size_;
CPURegister::RegisterType type_;
bool is_valid() const {
constexpr RegList kValidRegisters{0x8000000ffffffff};
constexpr RegList kValidVRegisters{0x0000000ffffffff};
switch (type_) {
case CPURegister::kRegister:
return (list_ & kValidRegisters) == list_;
case CPURegister::kVRegister:
return (list_ & kValidVRegisters) == list_;
case CPURegister::kNoRegister:
return list_ == 0;
default:
UNREACHABLE();
}
}
};
// AAPCS64 callee-saved registers.
#define kCalleeSaved CPURegList::GetCalleeSaved()
#define kCalleeSavedV CPURegList::GetCalleeSavedV()
// AAPCS64 caller-saved registers. Note that this includes lr.
#define kCallerSaved CPURegList::GetCallerSaved()
#define kCallerSavedV CPURegList::GetCallerSavedV()
// Define a {RegisterName} method for {Register} and {VRegister}.
DEFINE_REGISTER_NAMES(Register, GENERAL_REGISTERS)
DEFINE_REGISTER_NAMES(VRegister, VECTOR_REGISTERS)

View File

@ -0,0 +1,176 @@
// Copyright 2022 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_ARM64_REGLIST_ARM64_H_
#define V8_CODEGEN_ARM64_REGLIST_ARM64_H_
#include "src/codegen/arm64/utils-arm64.h"
#include "src/codegen/register-arch.h"
#include "src/codegen/reglist-base.h"
#include "src/common/globals.h"
namespace v8 {
namespace internal {
using RegList = RegListBase<Register>;
using DoubleRegList = RegListBase<DoubleRegister>;
ASSERT_TRIVIALLY_COPYABLE(RegList);
ASSERT_TRIVIALLY_COPYABLE(DoubleRegList);
constexpr int kRegListSizeInBits = sizeof(RegList) * kBitsPerByte;
// -----------------------------------------------------------------------------
// Lists of registers.
class V8_EXPORT_PRIVATE CPURegList {
public:
template <typename... CPURegisters>
explicit CPURegList(CPURegister reg0, CPURegisters... regs)
: list_(base::fold(
[](uint64_t acc, CPURegister v) {
if (!v.is_valid()) return acc;
return acc | (uint64_t{1} << v.code());
},
0, reg0, regs...)),
size_(reg0.SizeInBits()),
type_(reg0.type()) {
DCHECK(AreSameSizeAndType(reg0, regs...));
DCHECK(is_valid());
}
CPURegList(int size, RegList list)
: list_(list.bits()), size_(size), type_(CPURegister::kRegister) {
DCHECK(is_valid());
}
CPURegList(int size, DoubleRegList list)
: list_(list.bits()), size_(size), type_(CPURegister::kVRegister) {
DCHECK(is_valid());
}
CPURegList(CPURegister::RegisterType type, int size, int first_reg,
int last_reg)
: size_(size), type_(type) {
DCHECK(
((type == CPURegister::kRegister) && (last_reg < kNumberOfRegisters)) ||
((type == CPURegister::kVRegister) &&
(last_reg < kNumberOfVRegisters)));
DCHECK(last_reg >= first_reg);
list_ = (1ULL << (last_reg + 1)) - 1;
list_ &= ~((1ULL << first_reg) - 1);
DCHECK(is_valid());
}
CPURegister::RegisterType type() const { return type_; }
uint64_t bits() const { return list_; }
inline void set_bits(uint64_t new_bits) {
list_ = new_bits;
DCHECK(is_valid());
}
// Combine another CPURegList into this one. Registers that already exist in
// this list are left unchanged. The type and size of the registers in the
// 'other' list must match those in this list.
void Combine(const CPURegList& other);
// Remove every register in the other CPURegList from this one. Registers that
// do not exist in this list are ignored. The type of the registers in the
// 'other' list must match those in this list.
void Remove(const CPURegList& other);
// Variants of Combine and Remove which take CPURegisters.
void Combine(const CPURegister& other);
void Remove(const CPURegister& other1, const CPURegister& other2 = NoCPUReg,
const CPURegister& other3 = NoCPUReg,
const CPURegister& other4 = NoCPUReg);
// Variants of Combine and Remove which take a single register by its code;
// the type and size of the register is inferred from this list.
void Combine(int code);
void Remove(int code);
// Align the list to 16 bytes.
void Align();
CPURegister PopLowestIndex();
CPURegister PopHighestIndex();
// AAPCS64 callee-saved registers.
static CPURegList GetCalleeSaved(int size = kXRegSizeInBits);
static CPURegList GetCalleeSavedV(int size = kDRegSizeInBits);
// AAPCS64 caller-saved registers. Note that this includes lr.
// TODO(all): Determine how we handle d8-d15 being callee-saved, but the top
// 64-bits being caller-saved.
static CPURegList GetCallerSaved(int size = kXRegSizeInBits);
static CPURegList GetCallerSavedV(int size = kDRegSizeInBits);
bool IsEmpty() const { return list_ == 0; }
bool IncludesAliasOf(const CPURegister& other1,
const CPURegister& other2 = NoCPUReg,
const CPURegister& other3 = NoCPUReg,
const CPURegister& other4 = NoCPUReg) const {
uint64_t list = 0;
if (!other1.IsNone() && (other1.type() == type_)) {
list |= (uint64_t{1} << other1.code());
}
if (!other2.IsNone() && (other2.type() == type_)) {
list |= (uint64_t{1} << other2.code());
}
if (!other3.IsNone() && (other3.type() == type_)) {
list |= (uint64_t{1} << other3.code());
}
if (!other4.IsNone() && (other4.type() == type_)) {
list |= (uint64_t{1} << other4.code());
}
return (list_ & list) != 0;
}
int Count() const { return CountSetBits(list_, kRegListSizeInBits); }
int RegisterSizeInBits() const { return size_; }
int RegisterSizeInBytes() const {
int size_in_bits = RegisterSizeInBits();
DCHECK_EQ(size_in_bits % kBitsPerByte, 0);
return size_in_bits / kBitsPerByte;
}
int TotalSizeInBytes() const { return RegisterSizeInBytes() * Count(); }
private:
uint64_t list_;
int size_;
CPURegister::RegisterType type_;
bool is_valid() const {
constexpr uint64_t kValidRegisters{0x8000000ffffffff};
constexpr uint64_t kValidVRegisters{0x0000000ffffffff};
switch (type_) {
case CPURegister::kRegister:
return (list_ & kValidRegisters) == list_;
case CPURegister::kVRegister:
return (list_ & kValidVRegisters) == list_;
case CPURegister::kNoRegister:
return list_ == 0;
default:
UNREACHABLE();
}
}
};
// AAPCS64 callee-saved registers.
#define kCalleeSaved CPURegList::GetCalleeSaved()
#define kCalleeSavedV CPURegList::GetCalleeSavedV()
// AAPCS64 caller-saved registers. Note that this includes lr.
#define kCallerSaved CPURegList::GetCallerSaved()
#define kCallerSavedV CPURegList::GetCallerSavedV()
} // namespace internal
} // namespace v8
#endif // V8_CODEGEN_ARM64_REGLIST_ARM64_H_

View File

@ -24,8 +24,8 @@ void StaticCallInterfaceDescriptor<DerivedDescriptor>::
VerifyArgumentRegisterCount(CallInterfaceDescriptorData* data,
int nof_expected_args) {
RegList allocatable_regs = data->allocatable_registers();
if (nof_expected_args >= 1) DCHECK(allocatable_regs | esi.bit());
if (nof_expected_args >= 2) DCHECK(allocatable_regs | edi.bit());
if (nof_expected_args >= 1) DCHECK(allocatable_regs.has(esi));
if (nof_expected_args >= 2) DCHECK(allocatable_regs.has(edi));
// Additional arguments are passed on the stack.
}
#endif // DEBUG

View File

@ -428,22 +428,14 @@ void MacroAssembler::RecordWriteField(Register object, int offset,
}
void TurboAssembler::MaybeSaveRegisters(RegList registers) {
if (registers == 0) return;
ASM_CODE_COMMENT(this);
for (int i = 0; i < Register::kNumRegisters; ++i) {
if ((registers >> i) & 1u) {
push(Register::from_code(i));
}
for (Register reg : registers) {
push(reg);
}
}
void TurboAssembler::MaybeRestoreRegisters(RegList registers) {
if (registers == 0) return;
ASM_CODE_COMMENT(this);
for (int i = Register::kNumRegisters - 1; i >= 0; --i) {
if ((registers >> i) & 1u) {
pop(Register::from_code(i));
}
for (Register reg : base::Reversed(registers)) {
pop(reg);
}
}

View File

@ -6,8 +6,6 @@
#define V8_CODEGEN_IA32_REGISTER_IA32_H_
#include "src/codegen/register-base.h"
#include "src/codegen/register-configuration.h"
#include "src/codegen/reglist.h"
namespace v8 {
namespace internal {
@ -113,14 +111,6 @@ constexpr DoubleRegister no_dreg = DoubleRegister::no_reg();
// Note that the bit values must match those used in actual instruction encoding
constexpr int kNumRegs = 8;
// Caller-saved registers
constexpr RegList kJSCallerSaved =
Register::ListOf(eax, ecx, edx,
ebx, // used as caller-saved register in JavaScript code
edi); // callee function
constexpr int kNumJSCallerSaved = 5;
// Define {RegisterName} methods for the register types.
DEFINE_REGISTER_NAMES(Register, GENERAL_REGISTERS)
DEFINE_REGISTER_NAMES(XMMRegister, DOUBLE_REGISTERS)

View File

@ -0,0 +1,30 @@
// Copyright 2022 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_IA32_REGLIST_IA32_H_
#define V8_CODEGEN_IA32_REGLIST_IA32_H_
#include "src/codegen/register-arch.h"
#include "src/codegen/reglist-base.h"
namespace v8 {
namespace internal {
using RegList = RegListBase<Register>;
using DoubleRegList = RegListBase<DoubleRegister>;
ASSERT_TRIVIALLY_COPYABLE(RegList);
ASSERT_TRIVIALLY_COPYABLE(DoubleRegList);
// Caller-saved registers
constexpr RegList kJSCallerSaved = {
eax, ecx, edx,
ebx, // used as caller-saved register in JavaScript code
edi}; // callee function
constexpr int kNumJSCallerSaved = 5;
} // namespace internal
} // namespace v8
#endif // V8_CODEGEN_IA32_REGLIST_IA32_H_

View File

@ -217,24 +217,24 @@ constexpr Register WriteBarrierDescriptor::ValueRegister() {
constexpr RegList WriteBarrierDescriptor::ComputeSavedRegisters(
Register object, Register slot_address) {
DCHECK(!AreAliased(object, slot_address));
RegList saved_registers = 0;
RegList saved_registers;
#if V8_TARGET_ARCH_X64
// Only push clobbered registers.
if (object != ObjectRegister()) saved_registers |= ObjectRegister().bit();
if (object != ObjectRegister()) saved_registers.set(ObjectRegister());
if (slot_address != no_reg && slot_address != SlotAddressRegister()) {
saved_registers |= SlotAddressRegister().bit();
saved_registers.set(SlotAddressRegister());
}
#elif V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_LOONG64 || \
V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_MIPS
if (object != ObjectRegister()) saved_registers |= ObjectRegister().bit();
if (object != ObjectRegister()) saved_registers.set(ObjectRegister());
// The slot address is always clobbered.
saved_registers |= SlotAddressRegister().bit();
saved_registers.set(SlotAddressRegister());
#else
// TODO(cbruni): Enable callee-saved registers for other platforms.
// This is a temporary workaround to prepare code for callee-saved registers.
constexpr auto allocated_registers = registers();
for (size_t i = 0; i < allocated_registers.size(); ++i) {
saved_registers |= allocated_registers[i].bit();
saved_registers.set(allocated_registers[i]);
}
#endif
return saved_registers;

View File

@ -19,16 +19,16 @@ void CallInterfaceDescriptorData::InitializeRegisters(
#ifdef DEBUG
{
// Make sure that the registers are all valid, and don't alias each other.
RegList reglist = 0;
RegList reglist;
for (int i = 0; i < register_parameter_count; ++i) {
Register reg = registers[i];
DCHECK(reg.is_valid());
DCHECK_EQ(reglist & reg.bit(), 0);
DCHECK(!reglist.has(reg));
DCHECK_NE(reg, kRootRegister);
#ifdef V8_COMPRESS_POINTERS_IN_SHARED_CAGE
DCHECK_NE(reg, kPtrComprCageBaseRegister);
#endif
reglist = CombineRegLists(reglist, reg.bit());
reglist.set(reg);
}
}
#endif
@ -145,8 +145,8 @@ void WriteBarrierDescriptor::Verify(CallInterfaceDescriptorData* data) {
DCHECK_EQ(ObjectRegister(), kJSFunctionRegister);
// We need a certain set of registers by default:
RegList allocatable_regs = data->allocatable_registers();
DCHECK(allocatable_regs | kContextRegister.bit());
DCHECK(allocatable_regs | kReturnRegister0.bit());
DCHECK(allocatable_regs.has(kContextRegister));
DCHECK(allocatable_regs.has(kReturnRegister0));
VerifyArgumentRegisterCount(data, 4);
}
#endif // DEBUG

View File

@ -213,11 +213,11 @@ class V8_EXPORT_PRIVATE CallInterfaceDescriptorData {
StackArgumentOrder stack_order() const { return stack_order_; }
void RestrictAllocatableRegisters(const Register* registers, size_t num) {
DCHECK_EQ(allocatable_registers_, 0);
DCHECK(allocatable_registers_.is_empty());
for (size_t i = 0; i < num; ++i) {
allocatable_registers_ |= registers[i].bit();
allocatable_registers_.set(registers[i]);
}
DCHECK_GT(NumRegs(allocatable_registers_), 0);
DCHECK(!allocatable_registers_.is_empty());
}
RegList allocatable_registers() const { return allocatable_registers_; }
@ -249,7 +249,7 @@ class V8_EXPORT_PRIVATE CallInterfaceDescriptorData {
// Specifying the set of registers that could be used by the register
// allocator. Currently, it's only used by RecordWrite code stub.
RegList allocatable_registers_ = 0;
RegList allocatable_registers_;
// |registers_params_| defines registers that are used for parameter passing.
// |machine_types_| defines machine types for resulting values and incomping

View File

@ -167,7 +167,7 @@ void Assembler::AllocateAndInstallRequestedHeapObjects(Isolate* isolate) {
Assembler::Assembler(const AssemblerOptions& options,
std::unique_ptr<AssemblerBuffer> buffer)
: AssemblerBase(options, std::move(buffer)),
scratch_register_list_(t7.bit() | t6.bit()) {
scratch_register_list_({t7, t6}) {
reloc_info_writer.Reposition(buffer_start_ + buffer_->size(), pc_);
last_trampoline_pool_end_ = 0;

View File

@ -1093,11 +1093,11 @@ class V8_EXPORT_PRIVATE V8_NODISCARD UseScratchRegisterScope {
void Include(const RegList& list) { *available_ |= list; }
void Exclude(const RegList& list) { *available_ &= ~list; }
void Include(const Register& reg1, const Register& reg2 = no_reg) {
RegList list(reg1.bit() | reg2.bit());
RegList list({reg1, reg2});
Include(list);
}
void Exclude(const Register& reg1, const Register& reg2 = no_reg) {
RegList list(reg1.bit() | reg2.bit());
RegList list({reg1, reg2});
Exclude(list);
}

View File

@ -24,14 +24,14 @@ template <typename DerivedDescriptor>
void StaticCallInterfaceDescriptor<DerivedDescriptor>::
VerifyArgumentRegisterCount(CallInterfaceDescriptorData* data, int argc) {
RegList allocatable_regs = data->allocatable_registers();
if (argc >= 1) DCHECK(allocatable_regs | a0.bit());
if (argc >= 2) DCHECK(allocatable_regs | a1.bit());
if (argc >= 3) DCHECK(allocatable_regs | a2.bit());
if (argc >= 4) DCHECK(allocatable_regs | a3.bit());
if (argc >= 5) DCHECK(allocatable_regs | a4.bit());
if (argc >= 6) DCHECK(allocatable_regs | a5.bit());
if (argc >= 7) DCHECK(allocatable_regs | a6.bit());
if (argc >= 8) DCHECK(allocatable_regs | a7.bit());
if (argc >= 1) DCHECK(allocatable_regs.has(a0));
if (argc >= 2) DCHECK(allocatable_regs.has(a1));
if (argc >= 3) DCHECK(allocatable_regs.has(a2));
if (argc >= 4) DCHECK(allocatable_regs.has(a3));
if (argc >= 5) DCHECK(allocatable_regs.has(a4));
if (argc >= 6) DCHECK(allocatable_regs.has(a5));
if (argc >= 7) DCHECK(allocatable_regs.has(a6));
if (argc >= 8) DCHECK(allocatable_regs.has(a7));
// Additional arguments are passed on the stack.
}
#endif // DEBUG

View File

@ -51,22 +51,13 @@ int TurboAssembler::RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode,
Register exclusion2,
Register exclusion3) const {
int bytes = 0;
RegList exclusions = 0;
if (exclusion1 != no_reg) {
exclusions |= exclusion1.bit();
if (exclusion2 != no_reg) {
exclusions |= exclusion2.bit();
if (exclusion3 != no_reg) {
exclusions |= exclusion3.bit();
}
}
}
RegList list = kJSCallerSaved & ~exclusions;
bytes += NumRegs(list) * kPointerSize;
RegList exclusions = {exclusion1, exclusion2, exclusion3};
RegList list = kJSCallerSaved - exclusions;
bytes += list.Count() * kPointerSize;
if (fp_mode == SaveFPRegsMode::kSave) {
bytes += NumRegs(kCallerSavedFPU) * kDoubleSize;
bytes += kCallerSavedFPU.Count() * kDoubleSize;
}
return bytes;
@ -76,24 +67,15 @@ int TurboAssembler::PushCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
Register exclusion2, Register exclusion3) {
ASM_CODE_COMMENT(this);
int bytes = 0;
RegList exclusions = 0;
if (exclusion1 != no_reg) {
exclusions |= exclusion1.bit();
if (exclusion2 != no_reg) {
exclusions |= exclusion2.bit();
if (exclusion3 != no_reg) {
exclusions |= exclusion3.bit();
}
}
}
RegList list = kJSCallerSaved & ~exclusions;
RegList exclusions = {exclusion1, exclusion2, exclusion3};
RegList list = kJSCallerSaved - exclusions;
MultiPush(list);
bytes += NumRegs(list) * kPointerSize;
bytes += list.Count() * kPointerSize;
if (fp_mode == SaveFPRegsMode::kSave) {
MultiPushFPU(kCallerSavedFPU);
bytes += NumRegs(kCallerSavedFPU) * kDoubleSize;
bytes += kCallerSavedFPU.Count() * kDoubleSize;
}
return bytes;
@ -105,23 +87,13 @@ int TurboAssembler::PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
int bytes = 0;
if (fp_mode == SaveFPRegsMode::kSave) {
MultiPopFPU(kCallerSavedFPU);
bytes += NumRegs(kCallerSavedFPU) * kDoubleSize;
bytes += kCallerSavedFPU.Count() * kDoubleSize;
}
RegList exclusions = 0;
if (exclusion1 != no_reg) {
exclusions |= exclusion1.bit();
if (exclusion2 != no_reg) {
exclusions |= exclusion2.bit();
if (exclusion3 != no_reg) {
exclusions |= exclusion3.bit();
}
}
}
RegList list = kJSCallerSaved & ~exclusions;
RegList exclusions = {exclusion1, exclusion2, exclusion3};
RegList list = kJSCallerSaved - exclusions;
MultiPop(list);
bytes += NumRegs(list) * kPointerSize;
bytes += list.Count() * kPointerSize;
return bytes;
}
@ -193,25 +165,13 @@ void MacroAssembler::RecordWriteField(Register object, int offset,
}
void TurboAssembler::MaybeSaveRegisters(RegList registers) {
if (registers == 0) return;
RegList regs = 0;
for (int i = 0; i < Register::kNumRegisters; ++i) {
if ((registers >> i) & 1u) {
regs |= Register::from_code(i).bit();
}
}
MultiPush(regs);
if (registers.is_empty()) return;
MultiPush(registers);
}
void TurboAssembler::MaybeRestoreRegisters(RegList registers) {
if (registers == 0) return;
RegList regs = 0;
for (int i = 0; i < Register::kNumRegisters; ++i) {
if ((registers >> i) & 1u) {
regs |= Register::from_code(i).bit();
}
}
MultiPop(regs);
if (registers.is_empty()) return;
MultiPop(registers);
}
void TurboAssembler::CallEphemeronKeyBarrier(Register object, Operand offset,
@ -4101,19 +4061,13 @@ void TurboAssembler::CheckPageFlag(const Register& object, int mask,
Register GetRegisterThatIsNotOneOf(Register reg1, Register reg2, Register reg3,
Register reg4, Register reg5,
Register reg6) {
RegList regs = 0;
if (reg1.is_valid()) regs |= reg1.bit();
if (reg2.is_valid()) regs |= reg2.bit();
if (reg3.is_valid()) regs |= reg3.bit();
if (reg4.is_valid()) regs |= reg4.bit();
if (reg5.is_valid()) regs |= reg5.bit();
if (reg6.is_valid()) regs |= reg6.bit();
RegList regs = {reg1, reg2, reg3, reg4, reg5, reg6};
const RegisterConfiguration* config = RegisterConfiguration::Default();
for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
int code = config->GetAllocatableGeneralCode(i);
Register candidate = Register::from_code(code);
if (regs & candidate.bit()) continue;
if (regs.has(candidate)) continue;
return candidate;
}
UNREACHABLE();

View File

@ -7,8 +7,6 @@
#include "src/codegen/loong64/constants-loong64.h"
#include "src/codegen/register-base.h"
#include "src/codegen/register-configuration.h"
#include "src/codegen/reglist.h"
namespace v8 {
namespace internal {
@ -49,74 +47,6 @@ namespace internal {
// encoding.
const int kNumRegs = 32;
const RegList kJSCallerSaved = 1 << 4 | // a0
1 << 5 | // a1
1 << 6 | // a2
1 << 7 | // a3
1 << 8 | // a4
1 << 9 | // a5
1 << 10 | // a6
1 << 11 | // a7
1 << 12 | // t0
1 << 13 | // t1
1 << 14 | // t2
1 << 15 | // t3
1 << 16 | // t4
1 << 17 | // t5
1 << 20; // t8
const int kNumJSCallerSaved = 15;
// Callee-saved registers preserved when switching from C to JavaScript.
const RegList kCalleeSaved = 1 << 22 | // fp
1 << 23 | // s0
1 << 24 | // s1
1 << 25 | // s2
1 << 26 | // s3
1 << 27 | // s4
1 << 28 | // s5
1 << 29 | // s6 (roots in Javascript code)
1 << 30 | // s7 (cp in Javascript code)
1 << 31; // s8
const int kNumCalleeSaved = 10;
const RegList kCalleeSavedFPU = 1 << 24 | // f24
1 << 25 | // f25
1 << 26 | // f26
1 << 27 | // f27
1 << 28 | // f28
1 << 29 | // f29
1 << 30 | // f30
1 << 31; // f31
const int kNumCalleeSavedFPU = 8;
const RegList kCallerSavedFPU = 1 << 0 | // f0
1 << 1 | // f1
1 << 2 | // f2
1 << 3 | // f3
1 << 4 | // f4
1 << 5 | // f5
1 << 6 | // f6
1 << 7 | // f7
1 << 8 | // f8
1 << 9 | // f9
1 << 10 | // f10
1 << 11 | // f11
1 << 12 | // f12
1 << 13 | // f13
1 << 14 | // f14
1 << 15 | // f15
1 << 16 | // f16
1 << 17 | // f17
1 << 18 | // f18
1 << 19 | // f19
1 << 20 | // f20
1 << 21 | // f21
1 << 22 | // f22
1 << 23; // f23
// CPU Registers.
//
// 1) We would prefer to use an enum, but enum values are assignment-

View File

@ -0,0 +1,50 @@
// Copyright 2022 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can b in the
// LICENSE file.
#ifndef V8_CODEGEN_LOONG64_REGLIST_LOONG64_H_
#define V8_CODEGEN_LOONG64_REGLIST_LOONG64_H_
#include "src/codegen/loong64/constants-loong64.h"
#include "src/codegen/register-arch.h"
#include "src/codegen/reglist-base.h"
namespace v8 {
namespace internal {
using RegList = RegListBase<Register>;
using DoubleRegList = RegListBase<DoubleRegister>;
ASSERT_TRIVIALLY_COPYABLE(RegList);
ASSERT_TRIVIALLY_COPYABLE(DoubleRegList);
const RegList kJSCallerSaved = {a0, a1, a2, a3, a4, a5, a6, a7,
t0, t1, t2, t3, t4, t5, t8};
const int kNumJSCallerSaved = 15;
// Callee-saved registers preserved when switching from C to JavaScript.
const RegList kCalleeSaved = {fp, // fp
s0, // s0
s1, // s1
s2, // s2
s3, // s3
s4, // s4
s5, // s5
s6, // s6 (roots in Javascript code)
s7, // s7 (cp in Javascript code)
s8}; // s8
const int kNumCalleeSaved = 10;
const RegList kCalleeSavedFPU = {f24, f25, f26, f27, f28, f29, f30, f31};
const int kNumCalleeSavedFPU = 8;
const RegList kCallerSavedFPU = {f0, f1, f2, f3, f4, f5, f6, f7,
f8, f9, f10, f11, f12, f13, f14, f15,
f16, f17, f18, f19, f20, f21, f22, f23};
} // namespace internal
} // namespace v8
#endif // V8_CODEGEN_LOONG64_REGLIST_LOONG64_H_

View File

@ -290,8 +290,7 @@ const Instr kLwSwOffsetMask = kImm16Mask;
Assembler::Assembler(const AssemblerOptions& options,
std::unique_ptr<AssemblerBuffer> buffer)
: AssemblerBase(options, std::move(buffer)),
scratch_register_list_(at.bit()) {
: AssemblerBase(options, std::move(buffer)), scratch_register_list_({at}) {
reloc_info_writer.Reposition(buffer_start_ + buffer_->size(), pc_);
last_trampoline_pool_end_ = 0;

View File

@ -1905,11 +1905,11 @@ class V8_EXPORT_PRIVATE V8_NODISCARD UseScratchRegisterScope {
void Include(const RegList& list) { *available_ |= list; }
void Exclude(const RegList& list) { *available_ &= ~list; }
void Include(const Register& reg1, const Register& reg2 = no_reg) {
RegList list(reg1.bit() | reg2.bit());
RegList list({reg1, reg2});
Include(list);
}
void Exclude(const Register& reg1, const Register& reg2 = no_reg) {
RegList list(reg1.bit() | reg2.bit());
RegList list({reg1, reg2});
Exclude(list);
}

View File

@ -24,10 +24,10 @@ template <typename DerivedDescriptor>
void StaticCallInterfaceDescriptor<DerivedDescriptor>::
VerifyArgumentRegisterCount(CallInterfaceDescriptorData* data, int argc) {
RegList allocatable_regs = data->allocatable_registers();
if (argc >= 1) DCHECK(allocatable_regs | a0.bit());
if (argc >= 2) DCHECK(allocatable_regs | a1.bit());
if (argc >= 3) DCHECK(allocatable_regs | a2.bit());
if (argc >= 4) DCHECK(allocatable_regs | a3.bit());
if (argc >= 1) DCHECK(allocatable_regs.has(a0));
if (argc >= 2) DCHECK(allocatable_regs.has(a1));
if (argc >= 3) DCHECK(allocatable_regs.has(a2));
if (argc >= 4) DCHECK(allocatable_regs.has(a3));
// Additional arguments are passed on the stack.
}
#endif // DEBUG

View File

@ -51,22 +51,13 @@ int TurboAssembler::RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode,
Register exclusion2,
Register exclusion3) const {
int bytes = 0;
RegList exclusions = 0;
if (exclusion1 != no_reg) {
exclusions |= exclusion1.bit();
if (exclusion2 != no_reg) {
exclusions |= exclusion2.bit();
if (exclusion3 != no_reg) {
exclusions |= exclusion3.bit();
}
}
}
RegList list = kJSCallerSaved & ~exclusions;
bytes += NumRegs(list) * kPointerSize;
RegList exclusions = {exclusion1, exclusion2, exclusion3};
RegList list = kJSCallerSaved - exclusions;
bytes += list.Count() * kPointerSize;
if (fp_mode == SaveFPRegsMode::kSave) {
bytes += NumRegs(kCallerSavedFPU) * kDoubleSize;
bytes += kCallerSavedFPU.Count() * kDoubleSize;
}
return bytes;
@ -76,24 +67,15 @@ int TurboAssembler::PushCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
Register exclusion2, Register exclusion3) {
ASM_CODE_COMMENT(this);
int bytes = 0;
RegList exclusions = 0;
if (exclusion1 != no_reg) {
exclusions |= exclusion1.bit();
if (exclusion2 != no_reg) {
exclusions |= exclusion2.bit();
if (exclusion3 != no_reg) {
exclusions |= exclusion3.bit();
}
}
}
RegList list = kJSCallerSaved & ~exclusions;
RegList exclusions = {exclusion1, exclusion2, exclusion3};
RegList list = kJSCallerSaved - exclusions;
MultiPush(list);
bytes += NumRegs(list) * kPointerSize;
bytes += list.Count() * kPointerSize;
if (fp_mode == SaveFPRegsMode::kSave) {
MultiPushFPU(kCallerSavedFPU);
bytes += NumRegs(kCallerSavedFPU) * kDoubleSize;
bytes += kCallerSavedFPU.Count() * kDoubleSize;
}
return bytes;
@ -105,23 +87,13 @@ int TurboAssembler::PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
int bytes = 0;
if (fp_mode == SaveFPRegsMode::kSave) {
MultiPopFPU(kCallerSavedFPU);
bytes += NumRegs(kCallerSavedFPU) * kDoubleSize;
bytes += kCallerSavedFPU.Count() * kDoubleSize;
}
RegList exclusions = 0;
if (exclusion1 != no_reg) {
exclusions |= exclusion1.bit();
if (exclusion2 != no_reg) {
exclusions |= exclusion2.bit();
if (exclusion3 != no_reg) {
exclusions |= exclusion3.bit();
}
}
}
RegList list = kJSCallerSaved & ~exclusions;
RegList exclusions = {exclusion1, exclusion2, exclusion3};
RegList list = kJSCallerSaved - exclusions;
MultiPop(list);
bytes += NumRegs(list) * kPointerSize;
bytes += list.Count() * kPointerSize;
return bytes;
}
@ -215,25 +187,13 @@ void MacroAssembler::RecordWriteField(Register object, int offset,
}
void TurboAssembler::MaybeSaveRegisters(RegList registers) {
if (registers == 0) return;
RegList regs = 0;
for (int i = 0; i < Register::kNumRegisters; ++i) {
if ((registers >> i) & 1u) {
regs |= Register::from_code(i).bit();
}
}
MultiPush(regs);
if (registers.is_empty()) return;
MultiPush(registers);
}
void TurboAssembler::MaybeRestoreRegisters(RegList registers) {
if (registers == 0) return;
RegList regs = 0;
for (int i = 0; i < Register::kNumRegisters; ++i) {
if ((registers >> i) & 1u) {
regs |= Register::from_code(i).bit();
}
}
MultiPop(regs);
if (registers.is_empty()) return;
MultiPop(registers);
}
void TurboAssembler::CallEphemeronKeyBarrier(Register object,
@ -5576,19 +5536,13 @@ void TurboAssembler::CheckPageFlag(Register object, Register scratch, int mask,
Register GetRegisterThatIsNotOneOf(Register reg1, Register reg2, Register reg3,
Register reg4, Register reg5,
Register reg6) {
RegList regs = 0;
if (reg1.is_valid()) regs |= reg1.bit();
if (reg2.is_valid()) regs |= reg2.bit();
if (reg3.is_valid()) regs |= reg3.bit();
if (reg4.is_valid()) regs |= reg4.bit();
if (reg5.is_valid()) regs |= reg5.bit();
if (reg6.is_valid()) regs |= reg6.bit();
RegList regs = {reg1, reg2, reg3, reg4, reg5, reg6};
const RegisterConfiguration* config = RegisterConfiguration::Default();
for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
int code = config->GetAllocatableGeneralCode(i);
Register candidate = Register::from_code(code);
if (regs & candidate.bit()) continue;
if (regs.has(candidate)) continue;
return candidate;
}
UNREACHABLE();

View File

@ -7,8 +7,6 @@
#include "src/codegen/mips/constants-mips.h"
#include "src/codegen/register-base.h"
#include "src/codegen/register-configuration.h"
#include "src/codegen/reglist.h"
namespace v8 {
namespace internal {
@ -48,66 +46,10 @@ namespace internal {
// encoding.
const int kNumRegs = 32;
const RegList kJSCallerSaved = 1 << 2 | // v0
1 << 3 | // v1
1 << 4 | // a0
1 << 5 | // a1
1 << 6 | // a2
1 << 7 | // a3
1 << 8 | // t0
1 << 9 | // t1
1 << 10 | // t2
1 << 11 | // t3
1 << 12 | // t4
1 << 13 | // t5
1 << 14 | // t6
1 << 15; // t7
const int kNumJSCallerSaved = 14;
// Callee-saved registers preserved when switching from C to JavaScript.
const RegList kCalleeSaved = 1 << 16 | // s0
1 << 17 | // s1
1 << 18 | // s2
1 << 19 | // s3
1 << 20 | // s4
1 << 21 | // s5
1 << 22 | // s6 (roots in Javascript code)
1 << 23 | // s7 (cp in Javascript code)
1 << 30; // fp/s8
const int kNumCalleeSaved = 9;
const RegList kCalleeSavedFPU = 1 << 20 | // f20
1 << 22 | // f22
1 << 24 | // f24
1 << 26 | // f26
1 << 28 | // f28
1 << 30; // f30
const int kNumCalleeSavedFPU = 6;
const RegList kCallerSavedFPU = 1 << 0 | // f0
1 << 2 | // f2
1 << 4 | // f4
1 << 6 | // f6
1 << 8 | // f8
1 << 10 | // f10
1 << 12 | // f12
1 << 14 | // f14
1 << 16 | // f16
1 << 18; // f18
// Number of registers for which space is reserved in safepoints. Must be a
// multiple of 8.
const int kNumSafepointRegisters = 24;
// Define the list of registers actually saved at safepoints.
// Note that the number of saved registers may be smaller than the reserved
// space, i.e. kNumSafepointSavedRegisters <= kNumSafepointRegisters.
const RegList kSafepointSavedRegisters = kJSCallerSaved | kCalleeSaved;
const int kNumSafepointSavedRegisters = kNumJSCallerSaved + kNumCalleeSaved;
const int kUndefIndex = -1;
// Map with indexes on stack that corresponds to codes of saved registers.
const int kSafepointRegisterStackIndexMap[kNumRegs] = {kUndefIndex, // zero_reg

View File

@ -0,0 +1,57 @@
// Copyright 2022 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_MIPS_REGLIST_MIPS_H_
#define V8_CODEGEN_MIPS_REGLIST_MIPS_H_
#include "src/codegen/mips/constants-mips.h"
#include "src/codegen/register-arch.h"
#include "src/codegen/reglist-base.h"
namespace v8 {
namespace internal {
using RegList = RegListBase<Register>;
using DoubleRegList = RegListBase<DoubleRegister>;
ASSERT_TRIVIALLY_COPYABLE(RegList);
ASSERT_TRIVIALLY_COPYABLE(DoubleRegList);
const RegList kJSCallerSaved = {v0, v1, a0, a1, a2, a3, t0,
t1, t2, t3, t4, t5, t6, t7}
const int kNumJSCallerSaved = 14;
// Callee-saved registers preserved when switching from C to JavaScript.
const RegList kCalleeSaved = {s0, // s0
s1, // s1
s2, // s2
s3, // s3
s4, // s4
s5, // s5
s6, // s6 (roots in Javascript code)
s7, // s7 (cp in Javascript code)
fp}; // fp/s8
const int kNumCalleeSaved = 9;
const RegList kCalleeSavedFPU = {f20, f22, f24, f26, f28, f30};
const int kNumCalleeSavedFPU = 6;
const RegList kCallerSavedFPU = {f0, f2, f4, f6, f8, f10, f12, f14, f16, f18};
// Number of registers for which space is reserved in safepoints. Must be a
// multiple of 8.
const int kNumSafepointRegisters = 24;
// Define the list of registers actually saved at safepoints.
// Note that the number of saved registers may be smaller than the reserved
// space, i.e. kNumSafepointSavedRegisters <= kNumSafepointRegisters.
const RegList kSafepointSavedRegisters = kJSCallerSaved | kCalleeSaved;
const int kNumSafepointSavedRegisters = kNumJSCallerSaved + kNumCalleeSaved;
} // namespace internal
} // namespace v8
#endif // V8_CODEGEN_MIPS_REGLIST_MIPS_H_

View File

@ -265,7 +265,7 @@ const Instr kLwSwOffsetMask = kImm16Mask;
Assembler::Assembler(const AssemblerOptions& options,
std::unique_ptr<AssemblerBuffer> buffer)
: AssemblerBase(options, std::move(buffer)),
scratch_register_list_(at.bit() | s0.bit()) {
scratch_register_list_({at, s0}) {
if (CpuFeatures::IsSupported(MIPS_SIMD)) {
EnableCpuFeature(MIPS_SIMD);
}

View File

@ -1935,11 +1935,11 @@ class V8_EXPORT_PRIVATE V8_NODISCARD UseScratchRegisterScope {
void Include(const RegList& list) { *available_ |= list; }
void Exclude(const RegList& list) { *available_ &= ~list; }
void Include(const Register& reg1, const Register& reg2 = no_reg) {
RegList list(reg1.bit() | reg2.bit());
RegList list({reg1, reg2});
Include(list);
}
void Exclude(const Register& reg1, const Register& reg2 = no_reg) {
RegList list(reg1.bit() | reg2.bit());
RegList list({reg1, reg2});
Exclude(list);
}

View File

@ -24,14 +24,14 @@ template <typename DerivedDescriptor>
void StaticCallInterfaceDescriptor<DerivedDescriptor>::
VerifyArgumentRegisterCount(CallInterfaceDescriptorData* data, int argc) {
RegList allocatable_regs = data->allocatable_registers();
if (argc >= 1) DCHECK(allocatable_regs | a0.bit());
if (argc >= 2) DCHECK(allocatable_regs | a1.bit());
if (argc >= 3) DCHECK(allocatable_regs | a2.bit());
if (argc >= 4) DCHECK(allocatable_regs | a3.bit());
if (argc >= 5) DCHECK(allocatable_regs | a4.bit());
if (argc >= 6) DCHECK(allocatable_regs | a5.bit());
if (argc >= 7) DCHECK(allocatable_regs | a6.bit());
if (argc >= 8) DCHECK(allocatable_regs | a7.bit());
if (argc >= 1) DCHECK(allocatable_regs.has(a0));
if (argc >= 2) DCHECK(allocatable_regs.has(a1));
if (argc >= 3) DCHECK(allocatable_regs.has(a2));
if (argc >= 4) DCHECK(allocatable_regs.has(a3));
if (argc >= 5) DCHECK(allocatable_regs.has(a4));
if (argc >= 6) DCHECK(allocatable_regs.has(a5));
if (argc >= 7) DCHECK(allocatable_regs.has(a6));
if (argc >= 8) DCHECK(allocatable_regs.has(a7));
// Additional arguments are passed on the stack.
}
#endif // DEBUG

View File

@ -51,22 +51,12 @@ int TurboAssembler::RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode,
Register exclusion2,
Register exclusion3) const {
int bytes = 0;
RegList exclusions = 0;
if (exclusion1 != no_reg) {
exclusions |= exclusion1.bit();
if (exclusion2 != no_reg) {
exclusions |= exclusion2.bit();
if (exclusion3 != no_reg) {
exclusions |= exclusion3.bit();
}
}
}
RegList list = kJSCallerSaved & ~exclusions;
bytes += NumRegs(list) * kPointerSize;
RegList exclusions = {exclusion1, exclusion2, exclusion3};
RegList list = kJSCallerSaved - exclusions;
bytes += list.Count() * kPointerSize;
if (fp_mode == SaveFPRegsMode::kSave) {
bytes += NumRegs(kCallerSavedFPU) * kDoubleSize;
bytes += kCallerSavedFPU.Count() * kDoubleSize;
}
return bytes;
@ -76,24 +66,14 @@ int TurboAssembler::PushCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
Register exclusion2, Register exclusion3) {
ASM_CODE_COMMENT(this);
int bytes = 0;
RegList exclusions = 0;
if (exclusion1 != no_reg) {
exclusions |= exclusion1.bit();
if (exclusion2 != no_reg) {
exclusions |= exclusion2.bit();
if (exclusion3 != no_reg) {
exclusions |= exclusion3.bit();
}
}
}
RegList list = kJSCallerSaved & ~exclusions;
RegList exclusions = {exclusion1, exclusion2, exclusion3};
RegList list = kJSCallerSaved - exclusions;
MultiPush(list);
bytes += NumRegs(list) * kPointerSize;
bytes += list.Count() * kPointerSize;
if (fp_mode == SaveFPRegsMode::kSave) {
MultiPushFPU(kCallerSavedFPU);
bytes += NumRegs(kCallerSavedFPU) * kDoubleSize;
bytes += kCallerSavedFPU.Count() * kDoubleSize;
}
return bytes;
@ -105,23 +85,13 @@ int TurboAssembler::PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
int bytes = 0;
if (fp_mode == SaveFPRegsMode::kSave) {
MultiPopFPU(kCallerSavedFPU);
bytes += NumRegs(kCallerSavedFPU) * kDoubleSize;
bytes += kCallerSavedFPU.Count() * kDoubleSize;
}
RegList exclusions = 0;
if (exclusion1 != no_reg) {
exclusions |= exclusion1.bit();
if (exclusion2 != no_reg) {
exclusions |= exclusion2.bit();
if (exclusion3 != no_reg) {
exclusions |= exclusion3.bit();
}
}
}
RegList list = kJSCallerSaved & ~exclusions;
RegList exclusions = {exclusion1, exclusion2, exclusion3};
RegList list = kJSCallerSaved - exclusions;
MultiPop(list);
bytes += NumRegs(list) * kPointerSize;
bytes += list.Count() * kPointerSize;
return bytes;
}
@ -213,25 +183,13 @@ void MacroAssembler::RecordWriteField(Register object, int offset,
}
void TurboAssembler::MaybeSaveRegisters(RegList registers) {
if (registers == 0) return;
RegList regs = 0;
for (int i = 0; i < Register::kNumRegisters; ++i) {
if ((registers >> i) & 1u) {
regs |= Register::from_code(i).bit();
}
}
MultiPush(regs);
if (registers.is_empty()) return;
MultiPush(registers);
}
void TurboAssembler::MaybeRestoreRegisters(RegList registers) {
if (registers == 0) return;
RegList regs = 0;
for (int i = 0; i < Register::kNumRegisters; ++i) {
if ((registers >> i) & 1u) {
regs |= Register::from_code(i).bit();
}
}
MultiPop(regs);
if (registers.is_empty()) return;
MultiPop(registers);
}
void TurboAssembler::CallEphemeronKeyBarrier(Register object,
@ -6121,19 +6079,13 @@ void TurboAssembler::CheckPageFlag(Register object, Register scratch, int mask,
Register GetRegisterThatIsNotOneOf(Register reg1, Register reg2, Register reg3,
Register reg4, Register reg5,
Register reg6) {
RegList regs = 0;
if (reg1.is_valid()) regs |= reg1.bit();
if (reg2.is_valid()) regs |= reg2.bit();
if (reg3.is_valid()) regs |= reg3.bit();
if (reg4.is_valid()) regs |= reg4.bit();
if (reg5.is_valid()) regs |= reg5.bit();
if (reg6.is_valid()) regs |= reg6.bit();
RegList regs = {reg1, reg2, reg3, reg4, reg5, reg6};
const RegisterConfiguration* config = RegisterConfiguration::Default();
for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
int code = config->GetAllocatableGeneralCode(i);
Register candidate = Register::from_code(code);
if (regs & candidate.bit()) continue;
if (regs.has(candidate)) continue;
return candidate;
}
UNREACHABLE();

View File

@ -7,8 +7,6 @@
#include "src/codegen/mips64/constants-mips64.h"
#include "src/codegen/register-base.h"
#include "src/codegen/register-configuration.h"
#include "src/codegen/reglist.h"
namespace v8 {
namespace internal {
@ -47,56 +45,6 @@ namespace internal {
// encoding.
const int kNumRegs = 32;
const RegList kJSCallerSaved = 1 << 2 | // v0
1 << 3 | // v1
1 << 4 | // a0
1 << 5 | // a1
1 << 6 | // a2
1 << 7 | // a3
1 << 8 | // a4
1 << 9 | // a5
1 << 10 | // a6
1 << 11 | // a7
1 << 12 | // t0
1 << 13 | // t1
1 << 14 | // t2
1 << 15; // t3
const int kNumJSCallerSaved = 14;
// Callee-saved registers preserved when switching from C to JavaScript.
const RegList kCalleeSaved = 1 << 16 | // s0
1 << 17 | // s1
1 << 18 | // s2
1 << 19 | // s3
1 << 20 | // s4
1 << 21 | // s5
1 << 22 | // s6 (roots in Javascript code)
1 << 23 | // s7 (cp in Javascript code)
1 << 30; // fp/s8
const int kNumCalleeSaved = 9;
const RegList kCalleeSavedFPU = 1 << 20 | // f20
1 << 22 | // f22
1 << 24 | // f24
1 << 26 | // f26
1 << 28 | // f28
1 << 30; // f30
const int kNumCalleeSavedFPU = 6;
const RegList kCallerSavedFPU = 1 << 0 | // f0
1 << 2 | // f2
1 << 4 | // f4
1 << 6 | // f6
1 << 8 | // f8
1 << 10 | // f10
1 << 12 | // f12
1 << 14 | // f14
1 << 16 | // f16
1 << 18; // f18
// Number of registers for which space is reserved in safepoints. Must be a
// multiple of 8.
const int kNumSafepointRegisters = 24;

View File

@ -0,0 +1,57 @@
// Copyright 2022 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_MIPS64_REGLIST_MIPS64_H_
#define V8_CODEGEN_MIPS64_REGLIST_MIPS64_H_
#include "src/codegen/mips64/constants-mips64.h"
#include "src/codegen/register-arch.h"
#include "src/codegen/reglist-base.h"
namespace v8 {
namespace internal {
using RegList = RegListBase<Register>;
using DoubleRegList = RegListBase<DoubleRegister>;
ASSERT_TRIVIALLY_COPYABLE(RegList);
ASSERT_TRIVIALLY_COPYABLE(DoubleRegList);
const RegList kJSCallerSaved = {v0, v1, a0, a1, a2, a3, a4,
a5, a6, a7, t0, t1, t2, t3};
const int kNumJSCallerSaved = 14;
// Callee-saved registers preserved when switching from C to JavaScript.
const RegList kCalleeSaved = {s0, // s0
s1, // s1
s2, // s2
s3, // s3
s4, // s4
s5, // s5
s6, // s6 (roots in Javascript code)
s7, // s7 (cp in Javascript code)
fp}; // fp/s8
const int kNumCalleeSaved = 9;
const RegList kCalleeSavedFPU = {f20, f22, f24, f26, f28, f30};
const int kNumCalleeSavedFPU = 6;
const RegList kCallerSavedFPU = {f0, f2, f4, f6, f8, f10, f12, f14, f16, f18};
// Number of registers for which space is reserved in safepoints. Must be a
// multiple of 8.
const int kNumSafepointRegisters = 24;
// Define the list of registers actually saved at safepoints.
// Note that the number of saved registers may be smaller than the reserved
// space, i.e. kNumSafepointSavedRegisters <= kNumSafepointRegisters.
const RegList kSafepointSavedRegisters = kJSCallerSaved | kCalleeSaved;
const int kNumSafepointSavedRegisters = kNumJSCallerSaved + kNumCalleeSaved;
} // namespace internal
} // namespace v8
#endif // V8_CODEGEN_MIPS64_REGLIST_MIPS64_H_

View File

@ -226,7 +226,7 @@ void Assembler::AllocateAndInstallRequestedHeapObjects(Isolate* isolate) {
Assembler::Assembler(const AssemblerOptions& options,
std::unique_ptr<AssemblerBuffer> buffer)
: AssemblerBase(options, std::move(buffer)),
scratch_register_list_(ip.bit()),
scratch_register_list_({ip}),
constant_pool_builder_(kLoadPtrMaxReachBits, kLoadDoubleMaxReachBits) {
reloc_info_writer.Reposition(buffer_start_ + buffer_->size(), pc_);
@ -2109,11 +2109,7 @@ UseScratchRegisterScope::~UseScratchRegisterScope() {
Register UseScratchRegisterScope::Acquire() {
RegList* available = assembler_->GetScratchRegisterList();
DCHECK_NOT_NULL(available);
DCHECK_NE(*available, 0);
int index = static_cast<int>(base::bits::CountTrailingZeros32(*available));
Register reg = Register::from_code(index);
*available &= ~reg.bit();
return reg;
return available->PopFront();
}
} // namespace internal

View File

@ -24,14 +24,14 @@ template <typename DerivedDescriptor>
void StaticCallInterfaceDescriptor<DerivedDescriptor>::
VerifyArgumentRegisterCount(CallInterfaceDescriptorData* data, int argc) {
RegList allocatable_regs = data->allocatable_registers();
if (argc >= 1) DCHECK(allocatable_regs | r3.bit());
if (argc >= 2) DCHECK(allocatable_regs | r4.bit());
if (argc >= 3) DCHECK(allocatable_regs | r5.bit());
if (argc >= 4) DCHECK(allocatable_regs | r6.bit());
if (argc >= 5) DCHECK(allocatable_regs | r7.bit());
if (argc >= 6) DCHECK(allocatable_regs | r8.bit());
if (argc >= 7) DCHECK(allocatable_regs | r9.bit());
if (argc >= 8) DCHECK(allocatable_regs | r10.bit());
if (argc >= 1) DCHECK(allocatable_regs.has(r3));
if (argc >= 2) DCHECK(allocatable_regs.has(r4));
if (argc >= 3) DCHECK(allocatable_regs.has(r5));
if (argc >= 4) DCHECK(allocatable_regs.has(r6));
if (argc >= 5) DCHECK(allocatable_regs.has(r7));
if (argc >= 6) DCHECK(allocatable_regs.has(r8));
if (argc >= 7) DCHECK(allocatable_regs.has(r9));
if (argc >= 8) DCHECK(allocatable_regs.has(r10));
// Additional arguments are passed on the stack.
}
#endif // DEBUG

View File

@ -58,19 +58,10 @@ int TurboAssembler::RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode,
Register exclusion2,
Register exclusion3) const {
int bytes = 0;
RegList exclusions = 0;
if (exclusion1 != no_reg) {
exclusions |= exclusion1.bit();
if (exclusion2 != no_reg) {
exclusions |= exclusion2.bit();
if (exclusion3 != no_reg) {
exclusions |= exclusion3.bit();
}
}
}
RegList list = kJSCallerSaved & ~exclusions;
bytes += NumRegs(list) * kSystemPointerSize;
RegList exclusions = {exclusion1, exclusion2, exclusion3};
RegList list = kJSCallerSaved - exclusions;
bytes += list.Count() * kSystemPointerSize;
if (fp_mode == SaveFPRegsMode::kSave) {
bytes += kStackSavedSavedFPSizeInBytes;
@ -82,20 +73,11 @@ int TurboAssembler::RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode,
int TurboAssembler::PushCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
Register exclusion2, Register exclusion3) {
int bytes = 0;
RegList exclusions = 0;
if (exclusion1 != no_reg) {
exclusions |= exclusion1.bit();
if (exclusion2 != no_reg) {
exclusions |= exclusion2.bit();
if (exclusion3 != no_reg) {
exclusions |= exclusion3.bit();
}
}
}
RegList list = kJSCallerSaved & ~exclusions;
RegList exclusions = {exclusion1, exclusion2, exclusion3};
RegList list = kJSCallerSaved - exclusions;
MultiPush(list);
bytes += NumRegs(list) * kSystemPointerSize;
bytes += list.Count() * kSystemPointerSize;
if (fp_mode == SaveFPRegsMode::kSave) {
MultiPushF64AndV128(kCallerSavedDoubles, kCallerSavedDoubles);
@ -113,20 +95,10 @@ int TurboAssembler::PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
bytes += kStackSavedSavedFPSizeInBytes;
}
RegList exclusions = 0;
if (exclusion1 != no_reg) {
exclusions |= exclusion1.bit();
if (exclusion2 != no_reg) {
exclusions |= exclusion2.bit();
if (exclusion3 != no_reg) {
exclusions |= exclusion3.bit();
}
}
}
RegList list = kJSCallerSaved & ~exclusions;
RegList exclusions = {exclusion1, exclusion2, exclusion3};
RegList list = kJSCallerSaved - exclusions;
MultiPop(list);
bytes += NumRegs(list) * kSystemPointerSize;
bytes += list.Count() * kSystemPointerSize;
return bytes;
}
@ -507,14 +479,14 @@ void TurboAssembler::MultiPushF64AndV128(RegList dregs, RegList simd_regs,
// We still need to allocate empty space on the stack even if we
// are not pushing Simd registers (see kFixedFrameSizeFromFp).
addi(sp, sp,
Operand(-static_cast<int8_t>(NumRegs(simd_regs)) * kSimd128Size));
Operand(-static_cast<int8_t>(simd_regs.Count()) * kSimd128Size));
bind(&simd_pushed);
} else {
if (CpuFeatures::SupportsWasmSimd128()) {
MultiPushV128(simd_regs);
} else {
addi(sp, sp,
Operand(-static_cast<int8_t>(NumRegs(simd_regs)) * kSimd128Size));
Operand(-static_cast<int8_t>(simd_regs.Count()) * kSimd128Size));
}
}
#endif
@ -535,14 +507,14 @@ void TurboAssembler::MultiPopF64AndV128(RegList dregs, RegList simd_regs,
b(&simd_popped);
bind(&pop_empty_simd);
addi(sp, sp,
Operand(static_cast<int8_t>(NumRegs(simd_regs)) * kSimd128Size));
Operand(static_cast<int8_t>(simd_regs.Count()) * kSimd128Size));
bind(&simd_popped);
} else {
if (CpuFeatures::SupportsWasmSimd128()) {
MultiPopV128(simd_regs);
} else {
addi(sp, sp,
Operand(static_cast<int8_t>(NumRegs(simd_regs)) * kSimd128Size));
Operand(static_cast<int8_t>(simd_regs.Count()) * kSimd128Size));
}
}
#endif
@ -687,25 +659,13 @@ void MacroAssembler::RecordWriteField(Register object, int offset,
}
void TurboAssembler::MaybeSaveRegisters(RegList registers) {
if (registers == 0) return;
RegList regs = 0;
for (int i = 0; i < Register::kNumRegisters; ++i) {
if ((registers >> i) & 1u) {
regs |= Register::from_code(i).bit();
}
}
MultiPush(regs);
if (registers.is_empty()) return;
MultiPush(registers);
}
void TurboAssembler::MaybeRestoreRegisters(RegList registers) {
if (registers == 0) return;
RegList regs = 0;
for (int i = 0; i < Register::kNumRegisters; ++i) {
if ((registers >> i) & 1u) {
regs |= Register::from_code(i).bit();
}
}
MultiPop(regs);
if (registers.is_empty()) return;
MultiPop(registers);
}
void TurboAssembler::CallEphemeronKeyBarrier(Register object,
@ -3405,19 +3365,13 @@ void TurboAssembler::StoreF32LE(DoubleRegister dst, const MemOperand& mem,
Register GetRegisterThatIsNotOneOf(Register reg1, Register reg2, Register reg3,
Register reg4, Register reg5,
Register reg6) {
RegList regs = 0;
if (reg1.is_valid()) regs |= reg1.bit();
if (reg2.is_valid()) regs |= reg2.bit();
if (reg3.is_valid()) regs |= reg3.bit();
if (reg4.is_valid()) regs |= reg4.bit();
if (reg5.is_valid()) regs |= reg5.bit();
if (reg6.is_valid()) regs |= reg6.bit();
RegList regs = {reg1, reg2, reg3, reg4, reg5, reg6};
const RegisterConfiguration* config = RegisterConfiguration::Default();
for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
int code = config->GetAllocatableGeneralCode(i);
Register candidate = Register::from_code(code);
if (regs & candidate.bit()) continue;
if (regs.has(candidate)) continue;
return candidate;
}
UNREACHABLE();

View File

@ -6,8 +6,6 @@
#define V8_CODEGEN_PPC_REGISTER_PPC_H_
#include "src/codegen/register-base.h"
#include "src/codegen/register-configuration.h"
#include "src/codegen/reglist.h"
namespace v8 {
namespace internal {
@ -62,84 +60,6 @@ namespace internal {
V(cr8) V(cr9) V(cr10) V(cr11) V(cr12) V(cr15)
// clang-format on
// Register list in load/store instructions
// Note that the bit values must match those used in actual instruction encoding
// Caller-saved/arguments registers
const RegList kJSCallerSaved = 1 << 3 | // r3 a1
1 << 4 | // r4 a2
1 << 5 | // r5 a3
1 << 6 | // r6 a4
1 << 7 | // r7 a5
1 << 8 | // r8 a6
1 << 9 | // r9 a7
1 << 10 | // r10 a8
1 << 11;
const int kNumJSCallerSaved = 9;
// Return the code of the n-th caller-saved register available to JavaScript
// e.g. JSCallerSavedReg(0) returns r0.code() == 0
int JSCallerSavedCode(int n);
// Callee-saved registers preserved when switching from C to JavaScript
const RegList kCalleeSaved = 1 << 14 | // r14
1 << 15 | // r15
1 << 16 | // r16
1 << 17 | // r17
1 << 18 | // r18
1 << 19 | // r19
1 << 20 | // r20
1 << 21 | // r21
1 << 22 | // r22
1 << 23 | // r23
1 << 24 | // r24
1 << 25 | // r25
1 << 26 | // r26
1 << 27 | // r27
1 << 28 | // r28
1 << 29 | // r29
1 << 30 | // r20
1 << 31; // r31
const int kNumCalleeSaved = 18;
const RegList kCallerSavedDoubles = 1 << 0 | // d0
1 << 1 | // d1
1 << 2 | // d2
1 << 3 | // d3
1 << 4 | // d4
1 << 5 | // d5
1 << 6 | // d6
1 << 7 | // d7
1 << 8 | // d8
1 << 9 | // d9
1 << 10 | // d10
1 << 11 | // d11
1 << 12 | // d12
1 << 13; // d13
const int kNumCallerSavedDoubles = 14;
const RegList kCalleeSavedDoubles = 1 << 14 | // d14
1 << 15 | // d15
1 << 16 | // d16
1 << 17 | // d17
1 << 18 | // d18
1 << 19 | // d19
1 << 20 | // d20
1 << 21 | // d21
1 << 22 | // d22
1 << 23 | // d23
1 << 24 | // d24
1 << 25 | // d25
1 << 26 | // d26
1 << 27 | // d27
1 << 28 | // d28
1 << 29 | // d29
1 << 30 | // d30
1 << 31; // d31
const int kNumCalleeSavedDoubles = 18;
// The following constants describe the stack frame linkage area as

View File

@ -0,0 +1,59 @@
// Copyright 2022 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_PPC_REGLIST_PPC_H_
#define V8_CODEGEN_PPC_REGLIST_PPC_H_
#include "src/codegen/register-arch.h"
#include "src/codegen/reglist-base.h"
namespace v8 {
namespace internal {
using RegList = RegListBase<Register>;
using DoubleRegList = RegListBase<DoubleRegister>;
ASSERT_TRIVIALLY_COPYABLE(RegList);
ASSERT_TRIVIALLY_COPYABLE(DoubleRegList);
// Register list in load/store instructions
// Note that the bit values must match those used in actual instruction encoding
// Caller-saved/arguments registers
const RegList kJSCallerSaved = {r3, // a1
r4, // a2
r5, // a3
r6, // a4
r7, // a5
r8, // a6
r9, // a7
r10, // a8
r11};
const int kNumJSCallerSaved = 9;
// Return the code of the n-th caller-saved register available to JavaScript
// e.g. JSCallerSavedReg(0) returns r0.code() == 0
int JSCallerSavedCode(int n);
// Callee-saved registers preserved when switching from C to JavaScript
const RegList kCalleeSaved = {r14, r15, r16, r17, r18, r19, r20, r21, r22,
r23, r24, r25, r26, r27, r28, r29, r30, r31};
const int kNumCalleeSaved = 18;
const RegList kCallerSavedDoubles = {d0, d1, d2, d3, d4, d5, d6,
d7, d8, d9, d10, d11, d12, d13};
const int kNumCallerSavedDoubles = 14;
const RegList kCalleeSavedDoubles = {d14, d15, d16, d17, d18, d19,
d20, d21, d22, d23, d24, d25,
d26, d27, d28, d29, d30, d31};
const int kNumCalleeSavedDoubles = 18;
} // namespace internal
} // namespace v8
#endif // V8_CODEGEN_PPC_REGLIST_PPC_H_

View File

@ -0,0 +1,34 @@
// Copyright 2022 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-base.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
#endif // V8_CODEGEN_REGISTER_ARCH_H_

View File

@ -7,7 +7,6 @@
#include "src/base/bits.h"
#include "src/base/bounds.h"
#include "src/codegen/reglist.h"
#include "src/common/globals.h"
namespace v8 {
@ -39,11 +38,6 @@ class RegisterBase {
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 int8_t code() const {
@ -51,34 +45,6 @@ class RegisterBase {
return reg_code_;
}
constexpr RegList bit() const {
return is_valid() ? RegList{1} << code() : RegList{};
}
static constexpr SubType FirstOf(RegList list) {
DCHECK_NE(kEmptyRegList, list);
return SubType::from_code(base::bits::CountTrailingZerosNonZero(list));
}
static constexpr SubType TakeFirst(RegList* list) {
RegList value = *list;
SubType result = FirstOf(value);
result.RemoveFrom(list);
return result;
}
constexpr bool IsIn(RegList list) const { return list & bit(); }
constexpr void InsertInto(RegList* list) const {
DCHECK(!IsIn(*list));
*list |= bit();
}
constexpr void RemoveFrom(RegList* list) const {
DCHECK(IsIn(*list));
*list ^= bit();
}
inline constexpr bool operator==(SubType other) const {
return reg_code_ == other.reg_code_;
}

View File

@ -190,13 +190,13 @@ const RegisterConfiguration* RegisterConfiguration::Default() {
const RegisterConfiguration* RegisterConfiguration::RestrictGeneralRegisters(
RegList registers) {
int num = NumRegs(registers);
int num = registers.Count();
std::unique_ptr<int[]> codes{new int[num]};
std::unique_ptr<char const* []> names { new char const*[num] };
int counter = 0;
for (int i = 0; i < Default()->num_allocatable_general_registers(); ++i) {
auto reg = Register::from_code(Default()->GetAllocatableGeneralCode(i));
if (reg.bit() & registers) {
if (registers.has(reg)) {
DCHECK(counter < num);
codes[counter] = reg.code();
names[counter] = RegisterName(Register::from_code(i));

View File

@ -14,17 +14,6 @@
namespace v8 {
namespace internal {
// An architecture independent representation of the sets of registers available
// for instruction creation.
enum class AliasingKind {
// Registers alias a single register of every other size (e.g. Intel).
kOverlap,
// Registers alias two registers of the next smaller size (e.g. ARM).
kCombine,
// SIMD128 Registers are independent of every other size (e.g Riscv)
kIndependent
};
class V8_EXPORT_PRIVATE RegisterConfiguration {
public:
// Architecture independent maxes.

View File

@ -5,41 +5,12 @@
#ifndef V8_CODEGEN_REGISTER_H_
#define V8_CODEGEN_REGISTER_H_
#include "src/codegen/register-base.h"
#include "src/codegen/register-arch.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 {
#define LIST_REG(V) V,
static constexpr RegList kAllocatableGeneralRegisters = Register::ListOf(
ALLOCATABLE_GENERAL_REGISTERS(LIST_REG) Register::no_reg());
#undef LIST_REG
constexpr int AddArgumentPaddingSlots(int argument_count) {
return argument_count + ArgumentPaddingSlots(argument_count);
}
@ -62,36 +33,13 @@ template <typename RegType, typename... RegTypes,
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_different_regs = RegListBase<RegType>{first_reg, regs...}.Count();
int num_given_regs =
base::fold(CountIfValidRegisterFunctor{}, 0, first_reg, regs...);
return num_different_regs < num_given_regs;
}
#endif
class RegListIterator {
public:
class Iterator {
public:
explicit Iterator(RegList list) : list_(list) {}
Register operator*() { return Register::FirstOf(list_); }
void operator++() { Register::FirstOf(list_).RemoveFrom(&list_); }
bool operator!=(const Iterator& other) const {
return list_ != other.list_;
}
private:
RegList list_;
};
explicit RegListIterator(RegList list) : list_(list) {}
Iterator begin() const { return Iterator(list_); }
Iterator end() const { return Iterator(kEmptyRegList); }
private:
RegList list_;
};
} // namespace internal
} // namespace v8

232
src/codegen/reglist-base.h Normal file
View File

@ -0,0 +1,232 @@
// Copyright 2022 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_REGLIST_BASE_H_
#define V8_CODEGEN_REGLIST_BASE_H_
#include <cstdint>
#include <initializer_list>
#include "src/base/bits.h"
#include "src/base/iterator.h"
#include "src/base/template-utils.h"
namespace v8 {
namespace internal {
class Register;
template <typename RegisterT>
class RegListBase {
using num_registers_sized_storage_t = typename std::conditional<
RegisterT::kNumRegisters <= 16, uint16_t,
typename std::conditional<RegisterT::kNumRegisters <= 32, uint32_t,
uint64_t>::type>::type;
STATIC_ASSERT(RegisterT::kNumRegisters <= 64);
public:
class Iterator;
class ReverseIterator;
#ifdef V8_TARGET_ARCH_ARM64
// On ARM64 the sp register has the special value 63 (kSPRegInternalCode)
using storage_t = typename std::conditional<
std::is_same<RegisterT, v8::internal::Register>::value, uint64_t,
num_registers_sized_storage_t>::type;
#else
using storage_t = num_registers_sized_storage_t;
#endif
constexpr RegListBase() = default;
constexpr RegListBase(std::initializer_list<RegisterT> regs) {
for (RegisterT reg : regs) {
set(reg);
}
}
constexpr void set(RegisterT reg) {
if (!reg.is_valid()) return;
regs_ |= storage_t{1} << reg.code();
}
constexpr void clear(RegisterT reg) {
if (!reg.is_valid()) return;
regs_ &= ~(storage_t{1} << reg.code());
}
constexpr bool has(RegisterT reg) const {
if (!reg.is_valid()) return false;
return (regs_ & (storage_t{1} << reg.code())) != 0;
}
constexpr void clear(RegListBase other) { regs_ &= ~other.regs_; }
constexpr bool is_empty() const { return regs_ == 0; }
constexpr unsigned Count() const {
return base::bits::CountPopulation(regs_);
}
constexpr RegListBase operator&(const RegListBase other) const {
return RegListBase(regs_ & other.regs_);
}
constexpr RegListBase operator|(const RegListBase other) const {
return RegListBase(regs_ | other.regs_);
}
constexpr RegListBase operator^(const RegListBase other) const {
return RegListBase(regs_ ^ other.regs_);
}
constexpr RegListBase operator-(const RegListBase other) const {
return RegListBase(regs_ & ~other.regs_);
}
constexpr RegListBase operator|(const RegisterT reg) const {
return *this | RegListBase{reg};
}
constexpr RegListBase operator-(const RegisterT reg) const {
return *this - RegListBase{reg};
}
constexpr RegListBase& operator&=(const RegListBase other) {
regs_ &= other.regs_;
return *this;
}
constexpr RegListBase& operator|=(const RegListBase other) {
regs_ |= other.regs_;
return *this;
}
constexpr bool operator==(const RegListBase other) const {
return regs_ == other.regs_;
}
constexpr bool operator!=(const RegListBase other) const {
return regs_ != other.regs_;
}
constexpr RegisterT first() const {
DCHECK(!is_empty());
int first_code = base::bits::CountTrailingZerosNonZero(regs_);
return RegisterT::from_code(first_code);
}
constexpr RegisterT last() const {
DCHECK(!is_empty());
int last_code =
8 * sizeof(regs_) - 1 - base::bits::CountLeadingZeros(regs_);
return RegisterT::from_code(last_code);
}
constexpr RegisterT PopFirst() {
RegisterT reg = first();
clear(reg);
return reg;
}
constexpr storage_t bits() const { return regs_; }
inline Iterator begin() const;
inline Iterator end() const;
inline ReverseIterator rbegin() const;
inline ReverseIterator rend() const;
static RegListBase FromBits(storage_t bits) { return RegListBase(bits); }
template <storage_t bits>
static constexpr RegListBase FromBits() {
return RegListBase{bits};
}
private:
// Unchecked constructor. Only use for valid bits.
explicit constexpr RegListBase(storage_t bits) : regs_(bits) {}
storage_t regs_ = 0;
};
template <typename RegisterT>
class RegListBase<RegisterT>::Iterator
: public base::iterator<std::forward_iterator_tag, RegisterT> {
public:
RegisterT operator*() { return remaining_.first(); }
Iterator& operator++() {
remaining_.clear(remaining_.first());
return *this;
}
bool operator==(Iterator other) { return remaining_ == other.remaining_; }
bool operator!=(Iterator other) { return remaining_ != other.remaining_; }
private:
explicit Iterator(RegListBase<RegisterT> remaining) : remaining_(remaining) {}
friend class RegListBase;
RegListBase<RegisterT> remaining_;
};
template <typename RegisterT>
class RegListBase<RegisterT>::ReverseIterator
: public base::iterator<std::forward_iterator_tag, RegisterT> {
public:
RegisterT operator*() { return remaining_.last(); }
ReverseIterator& operator++() {
remaining_.clear(remaining_.last());
return *this;
}
bool operator==(ReverseIterator other) {
return remaining_ == other.remaining_;
}
bool operator!=(ReverseIterator other) {
return remaining_ != other.remaining_;
}
private:
explicit ReverseIterator(RegListBase<RegisterT> remaining)
: remaining_(remaining) {}
friend class RegListBase;
RegListBase<RegisterT> remaining_;
};
template <typename RegisterT>
typename RegListBase<RegisterT>::Iterator RegListBase<RegisterT>::begin()
const {
return Iterator{*this};
}
template <typename RegisterT>
typename RegListBase<RegisterT>::Iterator RegListBase<RegisterT>::end() const {
return Iterator{RegListBase<RegisterT>{}};
}
template <typename RegisterT>
typename RegListBase<RegisterT>::ReverseIterator
RegListBase<RegisterT>::rbegin() const {
return ReverseIterator{*this};
}
template <typename RegisterT>
typename RegListBase<RegisterT>::ReverseIterator RegListBase<RegisterT>::rend()
const {
return ReverseIterator{RegListBase<RegisterT>{}};
}
template <typename RegisterT>
inline std::ostream& operator<<(std::ostream& os,
RegListBase<RegisterT> reglist) {
os << "{";
for (bool first = true; !reglist.is_empty(); first = false) {
RegisterT reg = reglist.first();
reglist.clear(reg);
os << (first ? "" : ", ") << reg;
}
return os << "}";
}
} // namespace internal
} // namespace v8
#endif // V8_CODEGEN_REGLIST_BASE_H_

View File

@ -5,41 +5,39 @@
#ifndef V8_CODEGEN_REGLIST_H_
#define V8_CODEGEN_REGLIST_H_
#include <cstdint>
#include "src/base/bits.h"
#include "src/base/template-utils.h"
#if V8_TARGET_ARCH_IA32
#include "src/codegen/ia32/reglist-ia32.h"
#elif V8_TARGET_ARCH_X64
#include "src/codegen/x64/reglist-x64.h"
#elif V8_TARGET_ARCH_ARM64
#include "src/codegen/arm64/reglist-arm64.h"
#elif V8_TARGET_ARCH_ARM
#include "src/codegen/arm/reglist-arm.h"
#elif V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_PPC64
#include "src/codegen/ppc/reglist-ppc.h"
#elif V8_TARGET_ARCH_MIPS
#include "src/codegen/mips/reglist-mips.h"
#elif V8_TARGET_ARCH_MIPS64
#include "src/codegen/mips64/reglist-mips64.h"
#elif V8_TARGET_ARCH_LOONG64
#include "src/codegen/loong64/reglist-loong64.h"
#elif V8_TARGET_ARCH_S390
#include "src/codegen/s390/reglist-s390.h"
#elif V8_TARGET_ARCH_RISCV64
#include "src/codegen/riscv64/reglist-riscv64.h"
#else
#error Unknown architecture.
#endif
namespace v8 {
namespace internal {
// Register configurations.
#if V8_TARGET_ARCH_ARM64
using RegList = uint64_t;
#else
using RegList = uint32_t;
#endif
static constexpr RegList kEmptyRegList = {};
constexpr RegList kEmptyRegList = 0;
// Get the number of registers in a given register list.
constexpr int NumRegs(RegList list) {
return base::bits::CountPopulation(list);
}
namespace detail {
// Combine two RegLists by building the union of the contained registers.
// TODO(clemensb): Replace by constexpr lambda once we have C++17.
constexpr RegList CombineRegListsHelper(RegList list1, RegList list2) {
return list1 | list2;
}
} // namespace detail
// Combine several RegLists by building the union of the contained registers.
template <typename... RegLists>
constexpr RegList CombineRegLists(RegLists... lists) {
return base::fold(detail::CombineRegListsHelper, 0, lists...);
}
#define LIST_REG(V) V,
static constexpr RegList kAllocatableGeneralRegisters = {
ALLOCATABLE_GENERAL_REGISTERS(LIST_REG) Register::no_reg()};
#undef LIST_REG
} // namespace internal
} // namespace v8

View File

@ -214,7 +214,7 @@ Assembler::Assembler(const AssemblerOptions& options,
std::unique_ptr<AssemblerBuffer> buffer)
: AssemblerBase(options, std::move(buffer)),
VU(this),
scratch_register_list_(t3.bit() | t5.bit()),
scratch_register_list_({t3, t5}),
constpool_(this) {
reloc_info_writer.Reposition(buffer_start_ + buffer_->size(), pc_);

View File

@ -1796,11 +1796,11 @@ class V8_EXPORT_PRIVATE UseScratchRegisterScope {
void Include(const RegList& list) { *available_ |= list; }
void Exclude(const RegList& list) { *available_ &= ~list; }
void Include(const Register& reg1, const Register& reg2 = no_reg) {
RegList list(reg1.bit() | reg2.bit());
RegList list({reg1, reg2});
Include(list);
}
void Exclude(const Register& reg1, const Register& reg2 = no_reg) {
RegList list(reg1.bit() | reg2.bit());
RegList list({reg1, reg2});
Exclude(list);
}

View File

@ -25,14 +25,14 @@ template <typename DerivedDescriptor>
void StaticCallInterfaceDescriptor<DerivedDescriptor>::
VerifyArgumentRegisterCount(CallInterfaceDescriptorData* data, int argc) {
RegList allocatable_regs = data->allocatable_registers();
if (argc >= 1) DCHECK(allocatable_regs | a0.bit());
if (argc >= 2) DCHECK(allocatable_regs | a1.bit());
if (argc >= 3) DCHECK(allocatable_regs | a2.bit());
if (argc >= 4) DCHECK(allocatable_regs | a3.bit());
if (argc >= 5) DCHECK(allocatable_regs | a4.bit());
if (argc >= 6) DCHECK(allocatable_regs | a5.bit());
if (argc >= 7) DCHECK(allocatable_regs | a6.bit());
if (argc >= 8) DCHECK(allocatable_regs | a7.bit());
if (argc >= 1) DCHECK(allocatable_regs.has(a0));
if (argc >= 2) DCHECK(allocatable_regs.has(a1));
if (argc >= 3) DCHECK(allocatable_regs.has(a2));
if (argc >= 4) DCHECK(allocatable_regs.has(a3));
if (argc >= 5) DCHECK(allocatable_regs.has(a4));
if (argc >= 6) DCHECK(allocatable_regs.has(a5));
if (argc >= 7) DCHECK(allocatable_regs.has(a6));
if (argc >= 8) DCHECK(allocatable_regs.has(a7));
// Additional arguments are passed on the stack.
}
#endif // DEBUG

View File

@ -48,22 +48,13 @@ int TurboAssembler::RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode,
Register exclusion2,
Register exclusion3) const {
int bytes = 0;
RegList exclusions = 0;
if (exclusion1 != no_reg) {
exclusions |= exclusion1.bit();
if (exclusion2 != no_reg) {
exclusions |= exclusion2.bit();
if (exclusion3 != no_reg) {
exclusions |= exclusion3.bit();
}
}
}
RegList list = kJSCallerSaved & ~exclusions;
bytes += NumRegs(list) * kSystemPointerSize;
RegList exclusions = {exclusion1, exclusion2, exclusion3};
RegList list = kJSCallerSaved - exclusions;
bytes += list.Count() * kSystemPointerSize;
if (fp_mode == SaveFPRegsMode::kSave) {
bytes += NumRegs(kCallerSavedFPU) * kDoubleSize;
bytes += kCallerSavedFPU.Count() * kDoubleSize;
}
return bytes;
@ -72,24 +63,15 @@ int TurboAssembler::RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode,
int TurboAssembler::PushCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
Register exclusion2, Register exclusion3) {
int bytes = 0;
RegList exclusions = 0;
if (exclusion1 != no_reg) {
exclusions |= exclusion1.bit();
if (exclusion2 != no_reg) {
exclusions |= exclusion2.bit();
if (exclusion3 != no_reg) {
exclusions |= exclusion3.bit();
}
}
}
RegList list = kJSCallerSaved & ~exclusions;
RegList exclusions = {exclusion1, exclusion2, exclusion3};
RegList list = kJSCallerSaved - exclusions;
MultiPush(list);
bytes += NumRegs(list) * kSystemPointerSize;
bytes += list.Count() * kSystemPointerSize;
if (fp_mode == SaveFPRegsMode::kSave) {
MultiPushFPU(kCallerSavedFPU);
bytes += NumRegs(kCallerSavedFPU) * kDoubleSize;
bytes += kCallerSavedFPU.Count() * kDoubleSize;
}
return bytes;
@ -100,23 +82,13 @@ int TurboAssembler::PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
int bytes = 0;
if (fp_mode == SaveFPRegsMode::kSave) {
MultiPopFPU(kCallerSavedFPU);
bytes += NumRegs(kCallerSavedFPU) * kDoubleSize;
bytes += kCallerSavedFPU.Count() * kDoubleSize;
}
RegList exclusions = 0;
if (exclusion1 != no_reg) {
exclusions |= exclusion1.bit();
if (exclusion2 != no_reg) {
exclusions |= exclusion2.bit();
if (exclusion3 != no_reg) {
exclusions |= exclusion3.bit();
}
}
}
RegList list = kJSCallerSaved & ~exclusions;
RegList exclusions = {exclusion1, exclusion2, exclusion3};
RegList list = kJSCallerSaved - exclusions;
MultiPop(list);
bytes += NumRegs(list) * kSystemPointerSize;
bytes += list.Count() * kSystemPointerSize;
return bytes;
}
@ -205,25 +177,13 @@ void MacroAssembler::RecordWriteField(Register object, int offset,
}
void TurboAssembler::MaybeSaveRegisters(RegList registers) {
if (registers == 0) return;
RegList regs = 0;
for (int i = 0; i < Register::kNumRegisters; ++i) {
if ((registers >> i) & 1u) {
regs |= Register::from_code(i).bit();
}
}
MultiPush(regs);
if (registers.is_empty()) return;
MultiPush(registers);
}
void TurboAssembler::MaybeRestoreRegisters(RegList registers) {
if (registers == 0) return;
RegList regs = 0;
for (int i = 0; i < Register::kNumRegisters; ++i) {
if ((registers >> i) & 1u) {
regs |= Register::from_code(i).bit();
}
}
MultiPop(regs);
if (registers.is_empty()) return;
MultiPop(registers);
}
void TurboAssembler::CallEphemeronKeyBarrier(Register object,
@ -1693,20 +1653,19 @@ void TurboAssembler::li(Register rd, Operand j, LiFlags mode) {
}
}
static RegList t_regs = Register::ListOf(t0, t1, t2, t3, t4, t5, t6);
static RegList a_regs = Register::ListOf(a0, a1, a2, a3, a4, a5, a6, a7);
static RegList s_regs =
Register::ListOf(s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11);
static RegList t_regs = {t0, t1, t2, t3, t4, t5, t6};
static RegList a_regs = {a0, a1, a2, a3, a4, a5, a6, a7};
static RegList s_regs = {s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11};
void TurboAssembler::MultiPush(RegList regs) {
int16_t num_to_push = base::bits::CountPopulation(regs);
int16_t stack_offset = num_to_push * kSystemPointerSize;
#define TEST_AND_PUSH_REG(reg) \
if ((regs & reg.bit()) != 0) { \
if (regs.has(reg)) { \
stack_offset -= kSystemPointerSize; \
Sd(reg, MemOperand(sp, stack_offset)); \
regs &= ~reg.bit(); \
regs.clear(reg); \
}
#define T_REGS(V) V(t6) V(t5) V(t4) V(t3) V(t2) V(t1) V(t0)
@ -1746,10 +1705,10 @@ void TurboAssembler::MultiPop(RegList regs) {
int16_t stack_offset = 0;
#define TEST_AND_POP_REG(reg) \
if ((regs & reg.bit()) != 0) { \
if (regs.has(reg)) { \
Ld(reg, MemOperand(sp, stack_offset)); \
stack_offset += kSystemPointerSize; \
regs &= ~reg.bit(); \
regs.clear(reg); \
}
#define T_REGS(V) V(t0) V(t1) V(t2) V(t3) V(t4) V(t5) V(t6)
@ -4993,19 +4952,13 @@ void TurboAssembler::CheckPageFlag(Register object, Register scratch, int mask,
Register GetRegisterThatIsNotOneOf(Register reg1, Register reg2, Register reg3,
Register reg4, Register reg5,
Register reg6) {
RegList regs = 0;
if (reg1.is_valid()) regs |= reg1.bit();
if (reg2.is_valid()) regs |= reg2.bit();
if (reg3.is_valid()) regs |= reg3.bit();
if (reg4.is_valid()) regs |= reg4.bit();
if (reg5.is_valid()) regs |= reg5.bit();
if (reg6.is_valid()) regs |= reg6.bit();
RegList regs = {reg1, reg2, reg3, reg4, reg5, reg6};
const RegisterConfiguration* config = RegisterConfiguration::Default();
for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
int code = config->GetAllocatableGeneralCode(i);
Register candidate = Register::from_code(code);
if (regs & candidate.bit()) continue;
if (regs.has(candidate)) continue;
return candidate;
}
UNREACHABLE();

View File

@ -6,8 +6,6 @@
#define V8_CODEGEN_RISCV64_REGISTER_RISCV64_H_
#include "src/codegen/register-base.h"
#include "src/codegen/register-configuration.h"
#include "src/codegen/reglist.h"
#include "src/codegen/riscv64/constants-riscv64.h"
namespace v8 {
@ -123,7 +121,7 @@ const RegList kCalleeSavedFPU = 1 << 8 | // fs0
1 << 26 | // fs10
1 << 27; // fs11
const int kNumCalleeSavedFPU = NumRegs(kCalleeSavedFPU);
const int kNumCalleeSavedFPU = kCalleeSavedFPU.Count();
const RegList kCallerSavedFPU = 1 << 0 | // ft0
1 << 1 | // ft1
@ -146,7 +144,7 @@ const RegList kCallerSavedFPU = 1 << 0 | // ft0
1 << 30 | // ft10
1 << 31; // ft11
const int kNumCallerSavedFPU = NumRegs(kCallerSavedFPU);
const int kNumCallerSavedFPU = kCallerSavedFPU.Count();
// Number of registers for which space is reserved in safepoints. Must be a
// multiple of 8.

View File

@ -0,0 +1,64 @@
// Copyright 2022 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_RISCV64_REGLIST_RISCV64_H_
#define V8_CODEGEN_RISCV64_REGLIST_RISCV64_H_
#include "src/codegen/register-arch.h"
#include "src/codegen/reglist-base.h"
#include "src/codegen/riscv64/constants-riscv64.h"
namespace v8 {
namespace internal {
using RegList = RegListBase<Register>;
using DoubleRegList = RegListBase<DoubleRegister>;
ASSERT_TRIVIALLY_COPYABLE(RegList);
ASSERT_TRIVIALLY_COPYABLE(DoubleRegList);
const RegList kJSCallerSaved = {t0, t1, t2, a0, a1, a2, a3, a4, a5, a6, a7, t4};
const int kNumJSCallerSaved = 12;
// Callee-saved registers preserved when switching from C to JavaScript.
const RegList kCalleeSaved = {fp, // fp/s0
s1, // s1
s2, // s2
s3, // s3 scratch register
s4, // s4 scratch register 2
s5, // s5
s6, // s6 (roots in Javascript code)
s7, // s7 (cp in Javascript code)
s8, // s8
s9, // s9
s10, // s10
s11}; // s11
const int kNumCalleeSaved = 12;
const RegList kCalleeSavedFPU = {fs0, fs1, fs2, fs3, fs4, fs5,
fs6, fs7, fs8, fs9, fs10, fs11};
const int kNumCalleeSavedFPU = kCalleeSavedFPU.Count();
const RegList kCallerSavedFPU = {ft0, ft1, ft2, ft3, ft4, ft5, ft6,
ft7, fa0, fa1, fa2, fa3, fa4, fa5,
fa6, fa7, ft8, ft9, ft10, ft11};
const int kNumCallerSavedFPU = kCallerSavedFPU.Count();
// Number of registers for which space is reserved in safepoints. Must be a
// multiple of 8.
const int kNumSafepointRegisters = 32;
// Define the list of registers actually saved at safepoints.
// Note that the number of saved registers may be smaller than the reserved
// space, i.e. kNumSafepointSavedRegisters <= kNumSafepointRegisters.
const RegList kSafepointSavedRegisters = kJSCallerSaved | kCalleeSaved;
const int kNumSafepointSavedRegisters = kNumJSCallerSaved + kNumCalleeSaved;
} // namespace internal
} // namespace v8
#endif // V8_CODEGEN_RISCV64_REGLIST_RISCV64_H_

View File

@ -375,8 +375,7 @@ void Assembler::AllocateAndInstallRequestedHeapObjects(Isolate* isolate) {
Assembler::Assembler(const AssemblerOptions& options,
std::unique_ptr<AssemblerBuffer> buffer)
: AssemblerBase(options, std::move(buffer)),
scratch_register_list_(ip.bit()) {
: AssemblerBase(options, std::move(buffer)), scratch_register_list_({ip}) {
reloc_info_writer.Reposition(buffer_start_ + buffer_->size(), pc_);
last_bound_pos_ = 0;
relocations_.reserve(128);
@ -885,11 +884,7 @@ UseScratchRegisterScope::~UseScratchRegisterScope() {
Register UseScratchRegisterScope::Acquire() {
RegList* available = assembler_->GetScratchRegisterList();
DCHECK_NOT_NULL(available);
DCHECK_NE(*available, 0);
int index = static_cast<int>(base::bits::CountTrailingZeros32(*available));
Register reg = Register::from_code(index);
*available &= ~reg.bit();
return reg;
return available->PopFront();
}
} // namespace internal
} // namespace v8

View File

@ -24,14 +24,14 @@ template <typename DerivedDescriptor>
void StaticCallInterfaceDescriptor<DerivedDescriptor>::
VerifyArgumentRegisterCount(CallInterfaceDescriptorData* data, int argc) {
RegList allocatable_regs = data->allocatable_registers();
if (argc >= 1) DCHECK(allocatable_regs | r2.bit());
if (argc >= 2) DCHECK(allocatable_regs | r3.bit());
if (argc >= 3) DCHECK(allocatable_regs | r4.bit());
if (argc >= 4) DCHECK(allocatable_regs | r5.bit());
if (argc >= 5) DCHECK(allocatable_regs | r6.bit());
if (argc >= 6) DCHECK(allocatable_regs | r7.bit());
if (argc >= 7) DCHECK(allocatable_regs | r8.bit());
if (argc >= 8) DCHECK(allocatable_regs | r9.bit());
if (argc >= 1) DCHECK(allocatable_regs.has(r2));
if (argc >= 2) DCHECK(allocatable_regs.has(r3));
if (argc >= 3) DCHECK(allocatable_regs.has(r4));
if (argc >= 4) DCHECK(allocatable_regs.has(r5));
if (argc >= 5) DCHECK(allocatable_regs.has(r6));
if (argc >= 6) DCHECK(allocatable_regs.has(r7));
if (argc >= 7) DCHECK(allocatable_regs.has(r8));
if (argc >= 8) DCHECK(allocatable_regs.has(r9));
// Additional arguments are passed on the stack.
}
#endif // DEBUG

View File

@ -284,19 +284,10 @@ int TurboAssembler::RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode,
Register exclusion2,
Register exclusion3) const {
int bytes = 0;
RegList exclusions = 0;
if (exclusion1 != no_reg) {
exclusions |= exclusion1.bit();
if (exclusion2 != no_reg) {
exclusions |= exclusion2.bit();
if (exclusion3 != no_reg) {
exclusions |= exclusion3.bit();
}
}
}
RegList list = kJSCallerSaved & ~exclusions;
bytes += NumRegs(list) * kSystemPointerSize;
RegList exclusions = {exclusion1, exclusion2, exclusion3};
RegList list = kJSCallerSaved - exclusions;
bytes += list.Count() * kSystemPointerSize;
if (fp_mode == SaveFPRegsMode::kSave) {
bytes += kStackSavedSavedFPSizeInBytes;
@ -308,20 +299,11 @@ int TurboAssembler::RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode,
int TurboAssembler::PushCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
Register exclusion2, Register exclusion3) {
int bytes = 0;
RegList exclusions = 0;
if (exclusion1 != no_reg) {
exclusions |= exclusion1.bit();
if (exclusion2 != no_reg) {
exclusions |= exclusion2.bit();
if (exclusion3 != no_reg) {
exclusions |= exclusion3.bit();
}
}
}
RegList list = kJSCallerSaved & ~exclusions;
RegList exclusions = {exclusion1, exclusion2, exclusion3};
RegList list = kJSCallerSaved - exclusions;
MultiPush(list);
bytes += NumRegs(list) * kSystemPointerSize;
bytes += list.Count() * kSystemPointerSize;
if (fp_mode == SaveFPRegsMode::kSave) {
MultiPushF64OrV128(kCallerSavedDoubles);
@ -339,20 +321,10 @@ int TurboAssembler::PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
bytes += kStackSavedSavedFPSizeInBytes;
}
RegList exclusions = 0;
if (exclusion1 != no_reg) {
exclusions |= exclusion1.bit();
if (exclusion2 != no_reg) {
exclusions |= exclusion2.bit();
if (exclusion3 != no_reg) {
exclusions |= exclusion3.bit();
}
}
}
RegList list = kJSCallerSaved & ~exclusions;
RegList exclusions = {exclusion1, exclusion2, exclusion3};
RegList list = kJSCallerSaved - exclusions;
MultiPop(list);
bytes += NumRegs(list) * kSystemPointerSize;
bytes += list.Count() * kSystemPointerSize;
return bytes;
}
@ -753,14 +725,14 @@ void TurboAssembler::MultiPushF64OrV128(RegList dregs, Register location) {
MultiPushDoubles(dregs);
// We still need to allocate empty space on the stack as if
// Simd rgeisters were saved (see kFixedFrameSizeFromFp).
lay(sp, MemOperand(sp, -(NumRegs(dregs) * kDoubleSize)));
lay(sp, MemOperand(sp, -(dregs.Count() * kDoubleSize)));
bind(&simd_pushed);
} else {
if (CpuFeatures::SupportsWasmSimd128()) {
MultiPushV128(dregs);
} else {
MultiPushDoubles(dregs);
lay(sp, MemOperand(sp, -(NumRegs(dregs) * kDoubleSize)));
lay(sp, MemOperand(sp, -(dregs.Count() * kDoubleSize)));
}
}
#else
@ -783,14 +755,14 @@ void TurboAssembler::MultiPopF64OrV128(RegList dregs, Register location) {
b(&simd_popped);
bind(&pop_doubles);
// Simd not supported, only pop double registers.
lay(sp, MemOperand(sp, NumRegs(dregs) * kDoubleSize));
lay(sp, MemOperand(sp, dregs.Count() * kDoubleSize));
MultiPopDoubles(dregs);
bind(&simd_popped);
} else {
if (CpuFeatures::SupportsWasmSimd128()) {
MultiPopV128(dregs);
} else {
lay(sp, MemOperand(sp, NumRegs(dregs) * kDoubleSize));
lay(sp, MemOperand(sp, dregs.Count() * kDoubleSize));
MultiPopDoubles(dregs);
}
}
@ -947,25 +919,13 @@ void MacroAssembler::RecordWriteField(Register object, int offset,
}
void TurboAssembler::MaybeSaveRegisters(RegList registers) {
if (registers == 0) return;
RegList regs = 0;
for (int i = 0; i < Register::kNumRegisters; ++i) {
if ((registers >> i) & 1u) {
regs |= Register::from_code(i).bit();
}
}
MultiPush(regs);
if (registers.is_empty()) return;
MultiPush(registers);
}
void TurboAssembler::MaybeRestoreRegisters(RegList registers) {
if (registers == 0) return;
RegList regs = 0;
for (int i = 0; i < Register::kNumRegisters; ++i) {
if ((registers >> i) & 1u) {
regs |= Register::from_code(i).bit();
}
}
MultiPop(regs);
if (registers.is_empty()) return;
MultiPop(registers);
}
void TurboAssembler::CallEphemeronKeyBarrier(Register object,
@ -2455,19 +2415,13 @@ void TurboAssembler::CheckPageFlag(
Register GetRegisterThatIsNotOneOf(Register reg1, Register reg2, Register reg3,
Register reg4, Register reg5,
Register reg6) {
RegList regs = 0;
if (reg1.is_valid()) regs |= reg1.bit();
if (reg2.is_valid()) regs |= reg2.bit();
if (reg3.is_valid()) regs |= reg3.bit();
if (reg4.is_valid()) regs |= reg4.bit();
if (reg5.is_valid()) regs |= reg5.bit();
if (reg6.is_valid()) regs |= reg6.bit();
RegList regs = {reg1, reg2, reg3, reg4, reg5, reg6};
const RegisterConfiguration* config = RegisterConfiguration::Default();
for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
int code = config->GetAllocatableGeneralCode(i);
Register candidate = Register::from_code(code);
if (regs & candidate.bit()) continue;
if (regs.has(candidate)) continue;
return candidate;
}
UNREACHABLE();

View File

@ -6,8 +6,6 @@
#define V8_CODEGEN_S390_REGISTER_S390_H_
#include "src/codegen/register-base.h"
#include "src/codegen/register-configuration.h"
#include "src/codegen/reglist.h"
namespace v8 {
namespace internal {
@ -37,56 +35,6 @@ namespace internal {
V(cr8) V(cr9) V(cr10) V(cr11) V(cr12) V(cr15)
// clang-format on
// Register list in load/store instructions
// Note that the bit values must match those used in actual instruction encoding
// Caller-saved/arguments registers
const RegList kJSCallerSaved = 1 << 1 | 1 << 2 | // r2 a1
1 << 3 | // r3 a2
1 << 4 | // r4 a3
1 << 5; // r5 a4
const int kNumJSCallerSaved = 5;
// Callee-saved registers preserved when switching from C to JavaScript
const RegList kCalleeSaved =
1 << 6 | // r6 (argument passing in CEntryStub)
// (HandleScope logic in MacroAssembler)
1 << 7 | // r7 (argument passing in CEntryStub)
// (HandleScope logic in MacroAssembler)
1 << 8 | // r8 (argument passing in CEntryStub)
// (HandleScope logic in MacroAssembler)
1 << 9 | // r9 (HandleScope logic in MacroAssembler)
1 << 10 | // r10 (Roots register in Javascript)
1 << 11 | // r11 (fp in Javascript)
1 << 12 | // r12 (ip in Javascript)
1 << 13; // r13 (cp in Javascript)
// 1 << 15; // r15 (sp in Javascript)
const int kNumCalleeSaved = 8;
const RegList kCallerSavedDoubles = 1 << 0 | // d0
1 << 1 | // d1
1 << 2 | // d2
1 << 3 | // d3
1 << 4 | // d4
1 << 5 | // d5
1 << 6 | // d6
1 << 7; // d7
const int kNumCallerSavedDoubles = 8;
const RegList kCalleeSavedDoubles = 1 << 8 | // d8
1 << 9 | // d9
1 << 10 | // d10
1 << 11 | // d11
1 << 12 | // d12
1 << 13 | // d12
1 << 14 | // d12
1 << 15; // d13
const int kNumCalleeSavedDoubles = 8;
// The following constants describe the stack frame linkage area as
// defined by the ABI.

View File

@ -0,0 +1,57 @@
// Copyright 2022 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_S390_REGLIST_S390_H_
#define V8_CODEGEN_S390_REGLIST_S390_H_
#include "src/codegen/register-arch.h"
#include "src/codegen/reglist-base.h"
namespace v8 {
namespace internal {
using RegList = RegListBase<Register>;
using DoubleRegList = RegListBase<DoubleRegister>;
ASSERT_TRIVIALLY_COPYABLE(RegList);
ASSERT_TRIVIALLY_COPYABLE(DoubleRegList);
// Register list in load/store instructions
// Note that the bit values must match those used in actual instruction encoding
// Caller-saved/arguments registers
const RegList kJSCallerSaved = {r1, r2, // r2 a1
r3, // r3 a2
r4, // r4 a3
r5}; // r5 a4
const int kNumJSCallerSaved = 5;
// Callee-saved registers preserved when switching from C to JavaScript
const RegList kCalleeSaved = {r6, // r6 (argument passing in CEntryStub)
// (HandleScope logic in MacroAssembler)
r7, // r7 (argument passing in CEntryStub)
// (HandleScope logic in MacroAssembler)
r8, // r8 (argument passing in CEntryStub)
// (HandleScope logic in MacroAssembler)
r9, // r9 (HandleScope logic in MacroAssembler)
r10, // r10 (Roots register in Javascript)
r11, // r11 (fp in Javascript)
r12, // r12 (ip in Javascript)
r13}; // r13 (cp in Javascript)
// r15; // r15 (sp in Javascript)
const int kNumCalleeSaved = 8;
const RegList kCallerSavedDoubles = {d0, d1, d2, d3, d4, d5, d6, d7};
const int kNumCallerSavedDoubles = 8;
const RegList kCalleeSavedDoubles = {d8, d9, d10, d11, d12, d13, d14, d15};
const int kNumCalleeSavedDoubles = 8;
} // namespace internal
} // namespace v8
#endif // V8_CODEGEN_S390_REGLIST_S390_H_

View File

@ -24,10 +24,10 @@ void StaticCallInterfaceDescriptor<DerivedDescriptor>::
VerifyArgumentRegisterCount(CallInterfaceDescriptorData* data,
int nof_expected_args) {
RegList allocatable_regs = data->allocatable_registers();
if (nof_expected_args >= 1) DCHECK(allocatable_regs | arg_reg_1.bit());
if (nof_expected_args >= 2) DCHECK(allocatable_regs | arg_reg_2.bit());
if (nof_expected_args >= 3) DCHECK(allocatable_regs | arg_reg_3.bit());
if (nof_expected_args >= 4) DCHECK(allocatable_regs | arg_reg_4.bit());
if (nof_expected_args >= 1) DCHECK(allocatable_regs.has(arg_reg_1));
if (nof_expected_args >= 2) DCHECK(allocatable_regs.has(arg_reg_2));
if (nof_expected_args >= 3) DCHECK(allocatable_regs.has(arg_reg_3));
if (nof_expected_args >= 4) DCHECK(allocatable_regs.has(arg_reg_4));
// Additional arguments are passed on the stack.
}
#endif // DEBUG

View File

@ -442,22 +442,14 @@ void TurboAssembler::LoadExternalPointerField(
}
void TurboAssembler::MaybeSaveRegisters(RegList registers) {
if (registers == 0) return;
DCHECK_GT(NumRegs(registers), 0);
for (int i = 0; i < Register::kNumRegisters; ++i) {
if ((registers >> i) & 1u) {
pushq(Register::from_code(i));
}
for (Register reg : registers) {
pushq(reg);
}
}
void TurboAssembler::MaybeRestoreRegisters(RegList registers) {
if (registers == 0) return;
DCHECK_GT(NumRegs(registers), 0);
for (int i = Register::kNumRegisters - 1; i >= 0; --i) {
if ((registers >> i) & 1u) {
popq(Register::from_code(i));
}
for (Register reg : base::Reversed(registers)) {
popq(reg);
}
}

View File

@ -6,8 +6,6 @@
#define V8_CODEGEN_X64_REGISTER_X64_H_
#include "src/codegen/register-base.h"
#include "src/codegen/register-configuration.h"
#include "src/codegen/reglist.h"
namespace v8 {
namespace internal {
@ -87,20 +85,6 @@ constexpr Register no_reg = Register::no_reg();
constexpr int kNumRegs = 16;
constexpr RegList kJSCallerSaved =
Register::ListOf(rax, rcx, rdx,
rbx, // used as a caller-saved register in JavaScript code
rdi); // callee function
constexpr RegList kCallerSaved =
#ifdef V8_TARGET_OS_WIN
Register::ListOf(rax, rcx, rdx, r8, r9, r10, r11);
#else
Register::ListOf(rax, rcx, rdx, rdi, rsi, r8, r9, r10, r11);
#endif // V8_TARGET_OS_WIN
constexpr int kNumJSCallerSaved = 5;
#ifdef V8_TARGET_OS_WIN
// Windows calling convention
constexpr Register arg_reg_1 = rcx;

View File

@ -0,0 +1,37 @@
// Copyright 2022 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_X64_REGLIST_X64_H_
#define V8_CODEGEN_X64_REGLIST_X64_H_
#include "src/base/macros.h"
#include "src/codegen/register-arch.h"
#include "src/codegen/reglist-base.h"
namespace v8 {
namespace internal {
using RegList = RegListBase<Register>;
using DoubleRegList = RegListBase<DoubleRegister>;
ASSERT_TRIVIALLY_COPYABLE(RegList);
ASSERT_TRIVIALLY_COPYABLE(DoubleRegList);
constexpr RegList kJSCallerSaved = {
rax, rcx, rdx,
rbx, // used as a caller-saved register in JavaScript code
rdi}; // callee function
constexpr RegList kCallerSaved =
#ifdef V8_TARGET_OS_WIN
{rax, rcx, rdx, r8, r9, r10, r11};
#else
{rax, rcx, rdx, rdi, rsi, r8, r9, r10, r11};
#endif // V8_TARGET_OS_WIN
constexpr int kNumJSCallerSaved = 5;
} // namespace internal
} // namespace v8
#endif // V8_CODEGEN_X64_REGLIST_X64_H_

View File

@ -1719,6 +1719,17 @@ inline std::ostream& operator<<(std::ostream& os, ConcurrencyMode mode) {
return os << ToString(mode);
}
// An architecture independent representation of the sets of registers available
// for instruction creation.
enum class AliasingKind {
// Registers alias a single register of every other size (e.g. Intel).
kOverlap,
// Registers alias two registers of the next smaller size (e.g. ARM).
kCombine,
// SIMD128 Registers are independent of every other size (e.g Riscv)
kIndependent
};
#define FOR_EACH_ISOLATE_ADDRESS_NAME(C) \
C(Handler, handler) \
C(CEntryFP, c_entry_fp) \

View File

@ -516,7 +516,7 @@ void CodeGenerator::AssembleDeconstructFrame() {
void CodeGenerator::AssemblePrepareTailCall() {
if (frame_access_state()->has_frame()) {
__ ldm(ia, fp, lr.bit() | fp.bit());
__ ldm(ia, fp, {lr, fp});
}
frame_access_state()->SetFrameAccessToSP();
}
@ -3659,24 +3659,24 @@ void CodeGenerator::AssembleArchSelect(Instruction* instr,
void CodeGenerator::FinishFrame(Frame* frame) {
auto call_descriptor = linkage()->GetIncomingDescriptor();
const RegList saves_fp = call_descriptor->CalleeSavedFPRegisters();
if (saves_fp != 0) {
const DoubleRegList saves_fp = call_descriptor->CalleeSavedFPRegisters();
if (!saves_fp.is_empty()) {
frame->AlignSavedCalleeRegisterSlots();
}
if (saves_fp != 0) {
if (!saves_fp.is_empty()) {
// Save callee-saved FP registers.
STATIC_ASSERT(DwVfpRegister::kNumRegisters == 32);
uint32_t last = base::bits::CountLeadingZeros32(saves_fp) - 1;
uint32_t first = base::bits::CountTrailingZeros32(saves_fp);
DCHECK_EQ((last - first + 1), base::bits::CountPopulation(saves_fp));
uint32_t last = base::bits::CountLeadingZeros32(saves_fp.bits()) - 1;
uint32_t first = base::bits::CountTrailingZeros32(saves_fp.bits());
DCHECK_EQ((last - first + 1), saves_fp.Count());
frame->AllocateSavedCalleeRegisterSlots((last - first + 1) *
(kDoubleSize / kSystemPointerSize));
}
const RegList saves = call_descriptor->CalleeSavedRegisters();
if (saves != 0) {
if (!saves.is_empty()) {
// Save callee-saved registers.
frame->AllocateSavedCalleeRegisterSlots(base::bits::CountPopulation(saves));
frame->AllocateSavedCalleeRegisterSlots(saves.Count());
}
}
@ -3734,7 +3734,7 @@ void CodeGenerator::AssembleConstructFrame() {
}
const RegList saves = call_descriptor->CalleeSavedRegisters();
const RegList saves_fp = call_descriptor->CalleeSavedFPRegisters();
const DoubleRegList saves_fp = call_descriptor->CalleeSavedFPRegisters();
if (required_slots > 0) {
DCHECK(frame_access_state()->has_frame());
@ -3773,25 +3773,21 @@ void CodeGenerator::AssembleConstructFrame() {
#endif // V8_ENABLE_WEBASSEMBLY
// Skip callee-saved and return slots, which are pushed below.
required_slots -= base::bits::CountPopulation(saves);
required_slots -= saves.Count();
required_slots -= frame()->GetReturnSlotCount();
required_slots -= 2 * base::bits::CountPopulation(saves_fp);
required_slots -= 2 * saves_fp.Count();
if (required_slots > 0) {
__ AllocateStackSpace(required_slots * kSystemPointerSize);
}
}
if (saves_fp != 0) {
if (!saves_fp.is_empty()) {
// Save callee-saved FP registers.
STATIC_ASSERT(DwVfpRegister::kNumRegisters == 32);
uint32_t last = base::bits::CountLeadingZeros32(saves_fp) - 1;
uint32_t first = base::bits::CountTrailingZeros32(saves_fp);
DCHECK_EQ((last - first + 1), base::bits::CountPopulation(saves_fp));
__ vstm(db_w, sp, DwVfpRegister::from_code(first),
DwVfpRegister::from_code(last));
__ vstm(db_w, sp, saves_fp.first(), saves_fp.last());
}
if (saves != 0) {
if (!saves.is_empty()) {
// Save callee-saved registers.
__ stm(db_w, sp, saves);
}
@ -3812,18 +3808,15 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
// Restore registers.
const RegList saves = call_descriptor->CalleeSavedRegisters();
if (saves != 0) {
if (!saves.is_empty()) {
__ ldm(ia_w, sp, saves);
}
// Restore FP registers.
const RegList saves_fp = call_descriptor->CalleeSavedFPRegisters();
if (saves_fp != 0) {
const DoubleRegList saves_fp = call_descriptor->CalleeSavedFPRegisters();
if (!saves_fp.is_empty()) {
STATIC_ASSERT(DwVfpRegister::kNumRegisters == 32);
uint32_t last = base::bits::CountLeadingZeros32(saves_fp) - 1;
uint32_t first = base::bits::CountTrailingZeros32(saves_fp);
__ vldm(ia_w, sp, DwVfpRegister::from_code(first),
DwVfpRegister::from_code(last));
__ vldm(ia_w, sp, saves_fp.first(), saves_fp.last());
}
unwinding_info_writer_.MarkBlockWillExit();
@ -3868,7 +3861,7 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
if (drop_jsargs) {
// Get the actual argument count.
__ ldr(argc_reg, MemOperand(fp, StandardFrameConstants::kArgCOffset));
DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & argc_reg.bit());
DCHECK(!call_descriptor->CalleeSavedRegisters().has(argc_reg));
}
AssembleDeconstructFrame();
}
@ -3878,7 +3871,7 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
// The number of arguments without the receiver is
// max(argc_reg, parameter_slots-1), and the receiver is added in
// DropArguments().
DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & argc_reg.bit());
DCHECK(!call_descriptor->CalleeSavedRegisters().has(argc_reg));
if (parameter_slots > 1) {
__ cmp(argc_reg, Operand(parameter_slots));
__ mov(argc_reg, Operand(parameter_slots), LeaveCC, lt);

View File

@ -3005,17 +3005,17 @@ void CodeGenerator::FinishFrame(Frame* frame) {
auto call_descriptor = linkage()->GetIncomingDescriptor();
// Save FP registers.
CPURegList saves_fp = CPURegList(CPURegister::kVRegister, kDRegSizeInBits,
call_descriptor->CalleeSavedFPRegisters());
CPURegList saves_fp =
CPURegList(kDRegSizeInBits, call_descriptor->CalleeSavedFPRegisters());
int saved_count = saves_fp.Count();
if (saved_count != 0) {
DCHECK(saves_fp.list() == CPURegList::GetCalleeSavedV().list());
DCHECK(saves_fp.bits() == CPURegList::GetCalleeSavedV().bits());
frame->AllocateSavedCalleeRegisterSlots(saved_count *
(kDoubleSize / kSystemPointerSize));
}
CPURegList saves = CPURegList(CPURegister::kRegister, kXRegSizeInBits,
call_descriptor->CalleeSavedRegisters());
CPURegList saves =
CPURegList(kXRegSizeInBits, call_descriptor->CalleeSavedRegisters());
saved_count = saves.Count();
if (saved_count != 0) {
frame->AllocateSavedCalleeRegisterSlots(saved_count);
@ -3032,11 +3032,11 @@ void CodeGenerator::AssembleConstructFrame() {
int required_slots =
frame()->GetTotalFrameSlotCount() - frame()->GetFixedSlotCount();
CPURegList saves = CPURegList(CPURegister::kRegister, kXRegSizeInBits,
call_descriptor->CalleeSavedRegisters());
CPURegList saves =
CPURegList(kXRegSizeInBits, call_descriptor->CalleeSavedRegisters());
DCHECK_EQ(saves.Count() % 2, 0);
CPURegList saves_fp = CPURegList(CPURegister::kVRegister, kDRegSizeInBits,
call_descriptor->CalleeSavedFPRegisters());
CPURegList saves_fp =
CPURegList(kDRegSizeInBits, call_descriptor->CalleeSavedFPRegisters());
DCHECK_EQ(saves_fp.Count() % 2, 0);
// The number of return slots should be even after aligning the Frame.
const int returns = frame()->GetReturnSlotCount();
@ -3191,7 +3191,7 @@ void CodeGenerator::AssembleConstructFrame() {
// Save FP registers.
DCHECK_IMPLIES(saves_fp.Count() != 0,
saves_fp.list() == CPURegList::GetCalleeSavedV().list());
saves_fp.bits() == CPURegList::GetCalleeSavedV().bits());
__ PushCPURegList(saves_fp);
// Save registers.
@ -3211,13 +3211,13 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
}
// Restore registers.
CPURegList saves = CPURegList(CPURegister::kRegister, kXRegSizeInBits,
call_descriptor->CalleeSavedRegisters());
CPURegList saves =
CPURegList(kXRegSizeInBits, call_descriptor->CalleeSavedRegisters());
__ PopCPURegList<TurboAssembler::kAuthLR>(saves);
// Restore fp registers.
CPURegList saves_fp = CPURegList(CPURegister::kVRegister, kDRegSizeInBits,
call_descriptor->CalleeSavedFPRegisters());
CPURegList saves_fp =
CPURegList(kDRegSizeInBits, call_descriptor->CalleeSavedFPRegisters());
__ PopCPURegList(saves_fp);
unwinding_info_writer_.MarkBlockWillExit();
@ -3261,7 +3261,7 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
}
if (drop_jsargs) {
// Get the actual argument count.
DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & argc_reg.bit());
DCHECK(!call_descriptor->CalleeSavedRegisters().has(argc_reg));
__ Ldr(argc_reg, MemOperand(fp, StandardFrameConstants::kArgCOffset));
}
AssembleDeconstructFrame();
@ -3271,7 +3271,7 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
// We must pop all arguments from the stack (including the receiver). This
// number of arguments is given by max(1 + argc_reg, parameter_slots).
Label argc_reg_has_final_count;
DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & argc_reg.bit());
DCHECK(!call_descriptor->CalleeSavedRegisters().has(argc_reg));
if (parameter_slots > 1) {
__ Cmp(argc_reg, Operand(parameter_slots));
__ B(&argc_reg_has_final_count, ge);

View File

@ -3999,14 +3999,9 @@ void CodeGenerator::AssembleArchSelect(Instruction* instr,
void CodeGenerator::FinishFrame(Frame* frame) {
auto call_descriptor = linkage()->GetIncomingDescriptor();
const RegList saves = call_descriptor->CalleeSavedRegisters();
if (saves != 0) { // Save callee-saved registers.
if (!saves.is_empty()) { // Save callee-saved registers.
DCHECK(!info()->is_osr());
int pushed = 0;
for (int i = Register::kNumRegisters - 1; i >= 0; i--) {
if (!((1 << i) & saves)) continue;
++pushed;
}
frame->AllocateSavedCalleeRegisterSlots(pushed);
frame->AllocateSavedCalleeRegisterSlots(saves.Count());
}
}
@ -4096,17 +4091,17 @@ void CodeGenerator::AssembleConstructFrame() {
#endif // V8_ENABLE_WEBASSEMBLY
// Skip callee-saved and return slots, which are created below.
required_slots -= base::bits::CountPopulation(saves);
required_slots -= saves.Count();
required_slots -= frame()->GetReturnSlotCount();
if (required_slots > 0) {
__ AllocateStackSpace(required_slots * kSystemPointerSize);
}
}
if (saves != 0) { // Save callee-saved registers.
if (!saves.is_empty()) { // Save callee-saved registers.
DCHECK(!info()->is_osr());
for (int i = Register::kNumRegisters - 1; i >= 0; i--) {
if (((1 << i) & saves)) __ push(Register::from_code(i));
for (Register reg : base::Reversed(saves)) {
__ push(reg);
}
}
@ -4121,14 +4116,13 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
const RegList saves = call_descriptor->CalleeSavedRegisters();
// Restore registers.
if (saves != 0) {
if (!saves.is_empty()) {
const int returns = frame()->GetReturnSlotCount();
if (returns != 0) {
__ add(esp, Immediate(returns * kSystemPointerSize));
}
for (int i = 0; i < Register::kNumRegisters; i++) {
if (!((1 << i) & saves)) continue;
__ pop(Register::from_code(i));
for (Register reg : saves) {
__ pop(reg);
}
}
@ -4172,7 +4166,7 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
if (drop_jsargs) {
// Get the actual argument count.
__ mov(argc_reg, Operand(ebp, StandardFrameConstants::kArgCOffset));
DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & argc_reg.bit());
DCHECK(!call_descriptor->CalleeSavedRegisters().has(argc_reg));
}
AssembleDeconstructFrame();
}
@ -4185,8 +4179,8 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
Label mismatch_return;
Register scratch_reg = edx;
DCHECK_NE(argc_reg, scratch_reg);
DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & argc_reg.bit());
DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & scratch_reg.bit());
DCHECK(!call_descriptor->CalleeSavedRegisters().has(argc_reg));
DCHECK(!call_descriptor->CalleeSavedRegisters().has(scratch_reg));
__ cmp(argc_reg, Immediate(parameter_slots));
__ j(greater, &mismatch_return, Label::kNear);
__ Ret(parameter_slots * kSystemPointerSize, scratch_reg);
@ -4204,16 +4198,15 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
__ ret(static_cast<int>(pop_size));
} else {
Register scratch_reg = ecx;
DCHECK_EQ(0u,
call_descriptor->CalleeSavedRegisters() & scratch_reg.bit());
DCHECK(!call_descriptor->CalleeSavedRegisters().has(scratch_reg));
CHECK_LE(pop_size, static_cast<size_t>(std::numeric_limits<int>::max()));
__ Ret(static_cast<int>(pop_size), scratch_reg);
}
} else {
Register pop_reg = g.ToRegister(additional_pop_count);
Register scratch_reg = pop_reg == ecx ? edx : ecx;
DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & scratch_reg.bit());
DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & pop_reg.bit());
DCHECK(!call_descriptor->CalleeSavedRegisters().has(scratch_reg));
DCHECK(!call_descriptor->CalleeSavedRegisters().has(pop_reg));
int pop_size = static_cast<int>(parameter_slots * kSystemPointerSize);
__ PopReturnAddressTo(scratch_reg);
__ lea(esp, Operand(esp, pop_reg, times_system_pointer_size,

View File

@ -2181,7 +2181,7 @@ void CodeGenerator::AssembleArchSelect(Instruction* instr,
void CodeGenerator::FinishFrame(Frame* frame) {
auto call_descriptor = linkage()->GetIncomingDescriptor();
const RegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
const DoubleRegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
if (saves_fpu != 0) {
int count = base::bits::CountPopulation(saves_fpu);
DCHECK_EQ(kNumCalleeSavedFPU, count);
@ -2190,8 +2190,8 @@ void CodeGenerator::FinishFrame(Frame* frame) {
}
const RegList saves = call_descriptor->CalleeSavedRegisters();
if (saves != 0) {
int count = base::bits::CountPopulation(saves);
if (!saves.is_empty()) {
int count = saves.Count();
frame->AllocateSavedCalleeRegisterSlots(count);
}
}
@ -2249,7 +2249,7 @@ void CodeGenerator::AssembleConstructFrame() {
}
const RegList saves = call_descriptor->CalleeSavedRegisters();
const RegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
const DoubleRegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
if (required_slots > 0) {
DCHECK(frame_access_state()->has_frame());
@ -2293,7 +2293,7 @@ void CodeGenerator::AssembleConstructFrame() {
const int returns = frame()->GetReturnSlotCount();
// Skip callee-saved and return slots, which are pushed below.
required_slots -= base::bits::CountPopulation(saves);
required_slots -= saves.Count();
required_slots -= base::bits::CountPopulation(saves_fpu);
required_slots -= returns;
if (required_slots > 0) {
@ -2306,7 +2306,7 @@ void CodeGenerator::AssembleConstructFrame() {
DCHECK_EQ(kNumCalleeSavedFPU, base::bits::CountPopulation(saves_fpu));
}
if (saves != 0) {
if (!saves.is_empty()) {
// Save callee-saved registers.
__ MultiPush(saves);
}
@ -2327,12 +2327,12 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
// Restore GP registers.
const RegList saves = call_descriptor->CalleeSavedRegisters();
if (saves != 0) {
if (!saves.is_empty()) {
__ MultiPop(saves);
}
// Restore FPU registers.
const RegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
const DoubleRegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
if (saves_fpu != 0) {
__ MultiPopFPU(saves_fpu);
}

View File

@ -3934,7 +3934,7 @@ void CodeGenerator::AssembleArchSelect(Instruction* instr,
void CodeGenerator::FinishFrame(Frame* frame) {
auto call_descriptor = linkage()->GetIncomingDescriptor();
const RegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
const DoubleRegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
if (saves_fpu != 0) {
frame->AlignSavedCalleeRegisterSlots();
}
@ -3947,8 +3947,8 @@ void CodeGenerator::FinishFrame(Frame* frame) {
}
const RegList saves = call_descriptor->CalleeSavedRegisters();
if (saves != 0) {
int count = base::bits::CountPopulation(saves);
if (!saves.is_empty()) {
int count = saves.Count();
frame->AllocateSavedCalleeRegisterSlots(count);
}
}
@ -4005,7 +4005,7 @@ void CodeGenerator::AssembleConstructFrame() {
}
const RegList saves = call_descriptor->CalleeSavedRegisters();
const RegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
const DoubleRegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
if (required_slots > 0) {
DCHECK(frame_access_state()->has_frame());
@ -4046,7 +4046,7 @@ void CodeGenerator::AssembleConstructFrame() {
const int returns = frame()->GetReturnSlotCount();
// Skip callee-saved and return slots, which are pushed below.
required_slots -= base::bits::CountPopulation(saves);
required_slots -= saves.Count();
required_slots -= 2 * base::bits::CountPopulation(saves_fpu);
required_slots -= returns;
if (required_slots > 0) {
@ -4058,7 +4058,7 @@ void CodeGenerator::AssembleConstructFrame() {
__ MultiPushFPU(saves_fpu);
}
if (saves != 0) {
if (!saves.is_empty()) {
// Save callee-saved registers.
__ MultiPush(saves);
}
@ -4079,12 +4079,12 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
// Restore GP registers.
const RegList saves = call_descriptor->CalleeSavedRegisters();
if (saves != 0) {
if (!saves.is_empty()) {
__ MultiPop(saves);
}
// Restore FPU registers.
const RegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
const DoubleRegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
if (saves_fpu != 0) {
__ MultiPopFPU(saves_fpu);
}

View File

@ -4139,7 +4139,7 @@ void CodeGenerator::AssembleArchSelect(Instruction* instr,
void CodeGenerator::FinishFrame(Frame* frame) {
auto call_descriptor = linkage()->GetIncomingDescriptor();
const RegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
const DoubleRegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
if (saves_fpu != 0) {
int count = base::bits::CountPopulation(saves_fpu);
DCHECK_EQ(kNumCalleeSavedFPU, count);
@ -4148,8 +4148,8 @@ void CodeGenerator::FinishFrame(Frame* frame) {
}
const RegList saves = call_descriptor->CalleeSavedRegisters();
if (saves != 0) {
int count = base::bits::CountPopulation(saves);
if (!saves.is_empty()) {
int count = saves.Count();
frame->AllocateSavedCalleeRegisterSlots(count);
}
}
@ -4207,7 +4207,7 @@ void CodeGenerator::AssembleConstructFrame() {
}
const RegList saves = call_descriptor->CalleeSavedRegisters();
const RegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
const DoubleRegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
if (required_slots > 0) {
DCHECK(frame_access_state()->has_frame());
@ -4248,7 +4248,7 @@ void CodeGenerator::AssembleConstructFrame() {
const int returns = frame()->GetReturnSlotCount();
// Skip callee-saved and return slots, which are pushed below.
required_slots -= base::bits::CountPopulation(saves);
required_slots -= saves.Count();
required_slots -= base::bits::CountPopulation(saves_fpu);
required_slots -= returns;
if (required_slots > 0) {
@ -4261,7 +4261,7 @@ void CodeGenerator::AssembleConstructFrame() {
DCHECK_EQ(kNumCalleeSavedFPU, base::bits::CountPopulation(saves_fpu));
}
if (saves != 0) {
if (!saves.is_empty()) {
// Save callee-saved registers.
__ MultiPush(saves);
}
@ -4282,12 +4282,12 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
// Restore GP registers.
const RegList saves = call_descriptor->CalleeSavedRegisters();
if (saves != 0) {
if (!saves.is_empty()) {
__ MultiPop(saves);
}
// Restore FPU registers.
const RegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
const DoubleRegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
if (saves_fpu != 0) {
__ MultiPopFPU(saves_fpu);
}

View File

@ -3983,10 +3983,10 @@ void CodeGenerator::AssembleArchSelect(Instruction* instr,
void CodeGenerator::FinishFrame(Frame* frame) {
auto call_descriptor = linkage()->GetIncomingDescriptor();
const RegList double_saves = call_descriptor->CalleeSavedFPRegisters();
const DoubleRegList double_saves = call_descriptor->CalleeSavedFPRegisters();
// Save callee-saved Double registers.
if (double_saves != 0) {
if (double_ !saves.is_empty()) {
frame->AlignSavedCalleeRegisterSlots();
DCHECK_EQ(kNumCalleeSavedDoubles,
base::bits::CountPopulation(double_saves));
@ -3994,11 +3994,11 @@ void CodeGenerator::FinishFrame(Frame* frame) {
(kDoubleSize / kSystemPointerSize));
}
// Save callee-saved registers.
const RegList saves = FLAG_enable_embedded_constant_pool
? call_descriptor->CalleeSavedRegisters() &
~kConstantPoolRegister.bit()
: call_descriptor->CalleeSavedRegisters();
if (saves != 0) {
const RegList saves =
FLAG_enable_embedded_constant_pool
? call_descriptor->CalleeSavedRegisters() - kConstantPoolRegister
: call_descriptor->CalleeSavedRegisters();
if (!saves.is_empty()) {
// register save area does not include the fp or constant pool pointer.
const int num_saves =
kNumCalleeSaved - 1 - (FLAG_enable_embedded_constant_pool ? 1 : 0);
@ -4068,11 +4068,11 @@ void CodeGenerator::AssembleConstructFrame() {
required_slots -= osr_helper()->UnoptimizedFrameSlots();
}
const RegList saves_fp = call_descriptor->CalleeSavedFPRegisters();
const RegList saves = FLAG_enable_embedded_constant_pool
? call_descriptor->CalleeSavedRegisters() &
~kConstantPoolRegister.bit()
: call_descriptor->CalleeSavedRegisters();
const DoubleRegList saves_fp = call_descriptor->CalleeSavedFPRegisters();
const RegList saves =
FLAG_enable_embedded_constant_pool
? call_descriptor->CalleeSavedRegisters() - kConstantPoolRegister
: call_descriptor->CalleeSavedRegisters();
if (required_slots > 0) {
#if V8_ENABLE_WEBASSEMBLY
@ -4112,21 +4112,20 @@ void CodeGenerator::AssembleConstructFrame() {
#endif // V8_ENABLE_WEBASSEMBLY
// Skip callee-saved and return slots, which are pushed below.
required_slots -= base::bits::CountPopulation(saves);
required_slots -= saves.Count();
required_slots -= frame()->GetReturnSlotCount();
required_slots -= (kDoubleSize / kSystemPointerSize) *
base::bits::CountPopulation(saves_fp);
required_slots -= (kDoubleSize / kSystemPointerSize) * saves_fp.Count();
__ AddS64(sp, sp, Operand(-required_slots * kSystemPointerSize), r0);
}
// Save callee-saved Double registers.
if (saves_fp != 0) {
if (!saves_fp.is_empty()) {
__ MultiPushDoubles(saves_fp);
DCHECK_EQ(kNumCalleeSavedDoubles, base::bits::CountPopulation(saves_fp));
DCHECK_EQ(kNumCalleeSavedDoubles, saves_fp.Count());
}
// Save callee-saved registers.
if (saves != 0) {
if (!saves.is_empty()) {
__ MultiPush(saves);
// register save area does not include the fp or constant pool pointer.
}
@ -4146,24 +4145,24 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
}
// Restore registers.
const RegList saves = FLAG_enable_embedded_constant_pool
? call_descriptor->CalleeSavedRegisters() &
~kConstantPoolRegister.bit()
: call_descriptor->CalleeSavedRegisters();
if (saves != 0) {
const RegList saves =
FLAG_enable_embedded_constant_pool
? call_descriptor->CalleeSavedRegisters() - kConstantPoolRegister
: call_descriptor->CalleeSavedRegisters();
if (!saves.is_empty()) {
__ MultiPop(saves);
}
// Restore double registers.
const RegList double_saves = call_descriptor->CalleeSavedFPRegisters();
if (double_saves != 0) {
const DoubleRegList double_saves = call_descriptor->CalleeSavedFPRegisters();
if (double_ !saves.is_empty()) {
__ MultiPopDoubles(double_saves);
}
unwinding_info_writer_.MarkBlockWillExit();
// We might need r6 for scratch.
DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & r6.bit());
DCHECK(!call_descriptor->CalleeSavedRegisters().has(r6));
PPCOperandConverter g(this, nullptr);
const int parameter_slots =
static_cast<int>(call_descriptor->ParameterSlotCount());
@ -4204,7 +4203,7 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
}
if (drop_jsargs) {
// Get the actual argument count.
DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & argc_reg.bit());
DCHECK(!call_descriptor->CalleeSavedRegisters().has(argc_reg));
__ LoadU64(argc_reg, MemOperand(fp, StandardFrameConstants::kArgCOffset));
}
AssembleDeconstructFrame();

View File

@ -3850,7 +3850,7 @@ void CodeGenerator::AssembleArchTableSwitch(Instruction* instr) {
void CodeGenerator::FinishFrame(Frame* frame) {
auto call_descriptor = linkage()->GetIncomingDescriptor();
const RegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
const DoubleRegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
if (saves_fpu != 0) {
int count = base::bits::CountPopulation(saves_fpu);
DCHECK_EQ(kNumCalleeSavedFPU, count);
@ -3859,8 +3859,8 @@ void CodeGenerator::FinishFrame(Frame* frame) {
}
const RegList saves = call_descriptor->CalleeSavedRegisters();
if (saves != 0) {
int count = base::bits::CountPopulation(saves);
if (!saves.is_empty()) {
int count = saves.Count();
frame->AllocateSavedCalleeRegisterSlots(count);
}
}
@ -3911,7 +3911,7 @@ void CodeGenerator::AssembleConstructFrame() {
}
const RegList saves = call_descriptor->CalleeSavedRegisters();
const RegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
const DoubleRegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
if (required_slots > 0) {
DCHECK(frame_access_state()->has_frame());
@ -3951,7 +3951,7 @@ void CodeGenerator::AssembleConstructFrame() {
const int returns = frame()->GetReturnSlotCount();
// Skip callee-saved and return slots, which are pushed below.
required_slots -= base::bits::CountPopulation(saves);
required_slots -= saves.Count();
required_slots -= base::bits::CountPopulation(saves_fpu);
required_slots -= returns;
if (required_slots > 0) {
@ -3964,7 +3964,7 @@ void CodeGenerator::AssembleConstructFrame() {
DCHECK_EQ(kNumCalleeSavedFPU, base::bits::CountPopulation(saves_fpu));
}
if (saves != 0) {
if (!saves.is_empty()) {
// Save callee-saved registers.
__ MultiPush(saves);
}
@ -3985,12 +3985,12 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
// Restore GP registers.
const RegList saves = call_descriptor->CalleeSavedRegisters();
if (saves != 0) {
if (!saves.is_empty()) {
__ MultiPop(saves);
}
// Restore FPU registers.
const RegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
const DoubleRegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
if (saves_fpu != 0) {
__ MultiPopFPU(saves_fpu);
}

View File

@ -3359,10 +3359,10 @@ void CodeGenerator::AssembleArchSelect(Instruction* instr,
void CodeGenerator::FinishFrame(Frame* frame) {
auto call_descriptor = linkage()->GetIncomingDescriptor();
const RegList double_saves = call_descriptor->CalleeSavedFPRegisters();
const DoubleRegList double_saves = call_descriptor->CalleeSavedFPRegisters();
// Save callee-saved Double registers.
if (double_saves != 0) {
if (double_ !saves.is_empty()) {
frame->AlignSavedCalleeRegisterSlots();
DCHECK_EQ(kNumCalleeSavedDoubles,
base::bits::CountPopulation(double_saves));
@ -3371,7 +3371,7 @@ void CodeGenerator::FinishFrame(Frame* frame) {
}
// Save callee-saved registers.
const RegList saves = call_descriptor->CalleeSavedRegisters();
if (saves != 0) {
if (!saves.is_empty()) {
// register save area does not include the fp or constant pool pointer.
const int num_saves = kNumCalleeSaved - 1;
frame->AllocateSavedCalleeRegisterSlots(num_saves);
@ -3433,7 +3433,7 @@ void CodeGenerator::AssembleConstructFrame() {
required_slots -= osr_helper()->UnoptimizedFrameSlots();
}
const RegList saves_fp = call_descriptor->CalleeSavedFPRegisters();
const DoubleRegList saves_fp = call_descriptor->CalleeSavedFPRegisters();
const RegList saves = call_descriptor->CalleeSavedRegisters();
if (required_slots > 0) {
@ -3473,21 +3473,20 @@ void CodeGenerator::AssembleConstructFrame() {
#endif // V8_ENABLE_WEBASSEMBLY
// Skip callee-saved and return slots, which are pushed below.
required_slots -= base::bits::CountPopulation(saves);
required_slots -= saves.Count();
required_slots -= frame()->GetReturnSlotCount();
required_slots -= (kDoubleSize / kSystemPointerSize) *
base::bits::CountPopulation(saves_fp);
required_slots -= (kDoubleSize / kSystemPointerSize) * saves_fp.Count();
__ lay(sp, MemOperand(sp, -required_slots * kSystemPointerSize));
}
// Save callee-saved Double registers.
if (saves_fp != 0) {
if (!saves_fp.is_empty()) {
__ MultiPushDoubles(saves_fp);
DCHECK_EQ(kNumCalleeSavedDoubles, base::bits::CountPopulation(saves_fp));
DCHECK_EQ(kNumCalleeSavedDoubles, saves_fp.Count());
}
// Save callee-saved registers.
if (saves != 0) {
if (!saves.is_empty()) {
__ MultiPush(saves);
// register save area does not include the fp or constant pool pointer.
}
@ -3508,20 +3507,20 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
// Restore registers.
const RegList saves = call_descriptor->CalleeSavedRegisters();
if (saves != 0) {
if (!saves.is_empty()) {
__ MultiPop(saves);
}
// Restore double registers.
const RegList double_saves = call_descriptor->CalleeSavedFPRegisters();
if (double_saves != 0) {
const DoubleRegList double_saves = call_descriptor->CalleeSavedFPRegisters();
if (double_ !saves.is_empty()) {
__ MultiPopDoubles(double_saves);
}
unwinding_info_writer_.MarkBlockWillExit();
// We might need r3 for scratch.
DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & r5.bit());
DCHECK(!call_descriptor->CalleeSavedRegisters().has(r5));
S390OperandConverter g(this, nullptr);
const int parameter_slots =
static_cast<int>(call_descriptor->ParameterSlotCount());
@ -3562,7 +3561,7 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
}
if (drop_jsargs) {
// Get the actual argument count.
DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & argc_reg.bit());
DCHECK(!call_descriptor->CalleeSavedRegisters().has(argc_reg));
__ LoadU64(argc_reg, MemOperand(fp, StandardFrameConstants::kArgCOffset));
}
AssembleDeconstructFrame();

View File

@ -1076,8 +1076,9 @@ void AdjustStackPointerForTailCall(Instruction* instr,
// value before frame construction.
// See also: AssembleConstructFrame.
DCHECK(!info->is_osr());
DCHECK_EQ(linkage->GetIncomingDescriptor()->CalleeSavedRegisters(), 0);
DCHECK_EQ(linkage->GetIncomingDescriptor()->CalleeSavedFPRegisters(), 0);
DCHECK(linkage->GetIncomingDescriptor()->CalleeSavedRegisters().is_empty());
DCHECK(
linkage->GetIncomingDescriptor()->CalleeSavedFPRegisters().is_empty());
DCHECK_EQ(state->frame()->GetReturnSlotCount(), 0);
stack_slot_delta = (state->frame()->GetTotalFrameSlotCount() -
kReturnAddressStackSlotCount) *
@ -4580,22 +4581,16 @@ static const int kQuadWordSize = 16;
void CodeGenerator::FinishFrame(Frame* frame) {
CallDescriptor* call_descriptor = linkage()->GetIncomingDescriptor();
const RegList saves_fp = call_descriptor->CalleeSavedFPRegisters();
if (saves_fp != 0) { // Save callee-saved XMM registers.
const DoubleRegList saves_fp = call_descriptor->CalleeSavedFPRegisters();
if (!saves_fp.is_empty()) { // Save callee-saved XMM registers.
frame->AlignSavedCalleeRegisterSlots();
const uint32_t saves_fp_count = base::bits::CountPopulation(saves_fp);
const uint32_t saves_fp_count = saves_fp.Count();
frame->AllocateSavedCalleeRegisterSlots(
saves_fp_count * (kQuadWordSize / kSystemPointerSize));
}
const RegList saves = call_descriptor->CalleeSavedRegisters();
if (saves != 0) { // Save callee-saved registers.
int count = 0;
for (int i = Register::kNumRegisters - 1; i >= 0; i--) {
if (((1 << i) & saves)) {
++count;
}
}
frame->AllocateSavedCalleeRegisterSlots(count);
if (!saves.is_empty()) { // Save callee-saved registers.
frame->AllocateSavedCalleeRegisterSlots(saves.Count());
}
}
@ -4654,7 +4649,7 @@ void CodeGenerator::AssembleConstructFrame() {
}
const RegList saves = call_descriptor->CalleeSavedRegisters();
const RegList saves_fp = call_descriptor->CalleeSavedFPRegisters();
const DoubleRegList saves_fp = call_descriptor->CalleeSavedFPRegisters();
if (required_slots > 0) {
DCHECK(frame_access_state()->has_frame());
@ -4692,34 +4687,30 @@ void CodeGenerator::AssembleConstructFrame() {
#endif // V8_ENABLE_WEBASSEMBLY
// Skip callee-saved and return slots, which are created below.
required_slots -= base::bits::CountPopulation(saves);
required_slots -= base::bits::CountPopulation(saves_fp) *
(kQuadWordSize / kSystemPointerSize);
required_slots -= saves.Count();
required_slots -= saves_fp.Count() * (kQuadWordSize / kSystemPointerSize);
required_slots -= frame()->GetReturnSlotCount();
if (required_slots > 0) {
__ AllocateStackSpace(required_slots * kSystemPointerSize);
}
}
if (saves_fp != 0) { // Save callee-saved XMM registers.
const uint32_t saves_fp_count = base::bits::CountPopulation(saves_fp);
if (!saves_fp.is_empty()) { // Save callee-saved XMM registers.
const uint32_t saves_fp_count = saves_fp.Count();
const int stack_size = saves_fp_count * kQuadWordSize;
// Adjust the stack pointer.
__ AllocateStackSpace(stack_size);
// Store the registers on the stack.
int slot_idx = 0;
for (int i = 0; i < XMMRegister::kNumRegisters; i++) {
if (!((1 << i) & saves_fp)) continue;
__ Movdqu(Operand(rsp, kQuadWordSize * slot_idx),
XMMRegister::from_code(i));
for (XMMRegister reg : saves_fp) {
__ Movdqu(Operand(rsp, kQuadWordSize * slot_idx), reg);
slot_idx++;
}
}
if (saves != 0) { // Save callee-saved registers.
for (int i = Register::kNumRegisters - 1; i >= 0; i--) {
if (!((1 << i) & saves)) continue;
__ pushq(Register::from_code(i));
if (!saves.is_empty()) { // Save callee-saved registers.
for (Register reg : base::Reversed(saves)) {
__ pushq(reg);
}
}
@ -4734,26 +4725,23 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
// Restore registers.
const RegList saves = call_descriptor->CalleeSavedRegisters();
if (saves != 0) {
if (!saves.is_empty()) {
const int returns = frame()->GetReturnSlotCount();
if (returns != 0) {
__ addq(rsp, Immediate(returns * kSystemPointerSize));
}
for (int i = 0; i < Register::kNumRegisters; i++) {
if (!((1 << i) & saves)) continue;
__ popq(Register::from_code(i));
for (Register reg : saves) {
__ popq(reg);
}
}
const RegList saves_fp = call_descriptor->CalleeSavedFPRegisters();
if (saves_fp != 0) {
const uint32_t saves_fp_count = base::bits::CountPopulation(saves_fp);
const DoubleRegList saves_fp = call_descriptor->CalleeSavedFPRegisters();
if (!saves_fp.is_empty()) {
const uint32_t saves_fp_count = saves_fp.Count();
const int stack_size = saves_fp_count * kQuadWordSize;
// Load the registers from the stack.
int slot_idx = 0;
for (int i = 0; i < XMMRegister::kNumRegisters; i++) {
if (!((1 << i) & saves_fp)) continue;
__ Movdqu(XMMRegister::from_code(i),
Operand(rsp, kQuadWordSize * slot_idx));
for (XMMRegister reg : saves_fp) {
__ Movdqu(reg, Operand(rsp, kQuadWordSize * slot_idx));
slot_idx++;
}
// Adjust the stack pointer.
@ -4799,7 +4787,7 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
}
if (drop_jsargs) {
// Get the actual argument count.
DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & argc_reg.bit());
DCHECK(!call_descriptor->CalleeSavedRegisters().has(argc_reg));
__ movq(argc_reg, Operand(rbp, StandardFrameConstants::kArgCOffset));
}
AssembleDeconstructFrame();
@ -4813,8 +4801,8 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
Label mismatch_return;
Register scratch_reg = r10;
DCHECK_NE(argc_reg, scratch_reg);
DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & scratch_reg.bit());
DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & argc_reg.bit());
DCHECK(!call_descriptor->CalleeSavedRegisters().has(scratch_reg));
DCHECK(!call_descriptor->CalleeSavedRegisters().has(argc_reg));
__ cmpq(argc_reg, Immediate(parameter_slots));
__ j(greater, &mismatch_return, Label::kNear);
__ Ret(parameter_slots * kSystemPointerSize, scratch_reg);
@ -4825,7 +4813,7 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
__ Ret();
} else if (additional_pop_count->IsImmediate()) {
Register scratch_reg = r10;
DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & scratch_reg.bit());
DCHECK(!call_descriptor->CalleeSavedRegisters().has(scratch_reg));
int additional_count = g.ToConstant(additional_pop_count).ToInt32();
size_t pop_size = (parameter_slots + additional_count) * kSystemPointerSize;
CHECK_LE(pop_size, static_cast<size_t>(std::numeric_limits<int>::max()));
@ -4833,8 +4821,8 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
} else {
Register pop_reg = g.ToRegister(additional_pop_count);
Register scratch_reg = pop_reg == r10 ? rcx : r10;
DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & scratch_reg.bit());
DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & pop_reg.bit());
DCHECK(!call_descriptor->CalleeSavedRegisters().has(scratch_reg));
DCHECK(!call_descriptor->CalleeSavedRegisters().has(pop_reg));
int pop_size = static_cast<int>(parameter_slots * kSystemPointerSize);
__ PopReturnAddressTo(scratch_reg);
__ leaq(rsp, Operand(rsp, pop_reg, times_system_pointer_size,

View File

@ -19,7 +19,8 @@ namespace {
// ===========================================================================
// == ia32 ===================================================================
// ===========================================================================
#define CALLEE_SAVE_REGISTERS esi.bit() | edi.bit() | ebx.bit()
#define CALLEE_SAVE_REGISTERS esi, edi, ebx
#define CALLEE_SAVE_FP_REGISTERS
#elif V8_TARGET_ARCH_X64
// ===========================================================================
@ -32,21 +33,17 @@ namespace {
#define PARAM_REGISTERS rcx, rdx, r8, r9
#define FP_PARAM_REGISTERS xmm0, xmm1, xmm2, xmm3
#define FP_RETURN_REGISTER xmm0
#define CALLEE_SAVE_REGISTERS \
rbx.bit() | rdi.bit() | rsi.bit() | r12.bit() | r13.bit() | r14.bit() | \
r15.bit()
#define CALLEE_SAVE_FP_REGISTERS \
(1 << xmm6.code()) | (1 << xmm7.code()) | (1 << xmm8.code()) | \
(1 << xmm9.code()) | (1 << xmm10.code()) | (1 << xmm11.code()) | \
(1 << xmm12.code()) | (1 << xmm13.code()) | (1 << xmm14.code()) | \
(1 << xmm15.code())
#define CALLEE_SAVE_REGISTERS rbx, rdi, rsi, r12, r13, r14, r15
#define CALLEE_SAVE_FP_REGISTERS \
xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15
#else // V8_TARGET_OS_WIN
// == x64 other ==============================================================
#define PARAM_REGISTERS rdi, rsi, rdx, rcx, r8, r9
#define FP_PARAM_REGISTERS xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7
#define FP_RETURN_REGISTER xmm0
#define CALLEE_SAVE_REGISTERS \
rbx.bit() | r12.bit() | r13.bit() | r14.bit() | r15.bit()
#define CALLEE_SAVE_REGISTERS rbx, r12, r13, r14, r15
#define CALLEE_SAVE_FP_REGISTERS
#endif // V8_TARGET_OS_WIN
#elif V8_TARGET_ARCH_ARM
@ -54,12 +51,8 @@ namespace {
// == arm ====================================================================
// ===========================================================================
#define PARAM_REGISTERS r0, r1, r2, r3
#define CALLEE_SAVE_REGISTERS \
r4.bit() | r5.bit() | r6.bit() | r7.bit() | r8.bit() | r9.bit() | r10.bit()
#define CALLEE_SAVE_FP_REGISTERS \
(1 << d8.code()) | (1 << d9.code()) | (1 << d10.code()) | \
(1 << d11.code()) | (1 << d12.code()) | (1 << d13.code()) | \
(1 << d14.code()) | (1 << d15.code())
#define CALLEE_SAVE_REGISTERS r4, r5, r6, r7, r8, r9, r10
#define CALLEE_SAVE_FP_REGISTERS d8, d9, d10, d11, d12, d13, d14, d15
#elif V8_TARGET_ARCH_ARM64
// ===========================================================================
@ -68,16 +61,9 @@ namespace {
#define PARAM_REGISTERS x0, x1, x2, x3, x4, x5, x6, x7
#define FP_PARAM_REGISTERS d0, d1, d2, d3, d4, d5, d6, d7
#define FP_RETURN_REGISTER d0
#define CALLEE_SAVE_REGISTERS \
(1 << x19.code()) | (1 << x20.code()) | (1 << x21.code()) | \
(1 << x22.code()) | (1 << x23.code()) | (1 << x24.code()) | \
(1 << x25.code()) | (1 << x26.code()) | (1 << x27.code()) | \
(1 << x28.code())
#define CALLEE_SAVE_REGISTERS x19, x20, x21, x22, x23, x24, x25, x26, x27, x28
#define CALLEE_SAVE_FP_REGISTERS \
(1 << d8.code()) | (1 << d9.code()) | (1 << d10.code()) | \
(1 << d11.code()) | (1 << d12.code()) | (1 << d13.code()) | \
(1 << d14.code()) | (1 << d15.code())
#define CALLEE_SAVE_FP_REGISTERS d8, d9, d10, d11, d12, d13, d14, d15
#elif V8_TARGET_ARCH_MIPS
// ===========================================================================
@ -85,34 +71,24 @@ namespace {
// ===========================================================================
#define STACK_SHADOW_WORDS 4
#define PARAM_REGISTERS a0, a1, a2, a3
#define CALLEE_SAVE_REGISTERS \
s0.bit() | s1.bit() | s2.bit() | s3.bit() | s4.bit() | s5.bit() | s6.bit() | \
s7.bit()
#define CALLEE_SAVE_FP_REGISTERS \
f20.bit() | f22.bit() | f24.bit() | f26.bit() | f28.bit() | f30.bit()
#define CALLEE_SAVE_REGISTERS s0, s1, s2, s3, s4, s5, s6, s7
#define CALLEE_SAVE_FP_REGISTERS f20, f22, f24, f26, f28, f30
#elif V8_TARGET_ARCH_MIPS64
// ===========================================================================
// == mips64 =================================================================
// ===========================================================================
#define PARAM_REGISTERS a0, a1, a2, a3, a4, a5, a6, a7
#define CALLEE_SAVE_REGISTERS \
s0.bit() | s1.bit() | s2.bit() | s3.bit() | s4.bit() | s5.bit() | s6.bit() | \
s7.bit()
#define CALLEE_SAVE_FP_REGISTERS \
f20.bit() | f22.bit() | f24.bit() | f26.bit() | f28.bit() | f30.bit()
#define CALLEE_SAVE_REGISTERS s0, s1, s2, s3, s4, s5, s6, s7
#define CALLEE_SAVE_FP_REGISTERS f20, f22, f24, f26, f28, f30
#elif V8_TARGET_ARCH_LOONG64
// ===========================================================================
// == loong64 ================================================================
// ===========================================================================
#define PARAM_REGISTERS a0, a1, a2, a3, a4, a5, a6, a7
#define CALLEE_SAVE_REGISTERS \
s0.bit() | s1.bit() | s2.bit() | s3.bit() | s4.bit() | s5.bit() | s6.bit() | \
s7.bit() | s8.bit() | fp.bit()
#define CALLEE_SAVE_FP_REGISTERS \
f24.bit() | f25.bit() | f26.bit() | f27.bit() | f28.bit() | f29.bit() | \
f30.bit() | f31.bit()
#define CALLEE_SAVE_REGISTERS s0, s1, s2, s3, s4, s5, s6, s7, s8, fp
#define CALLEE_SAVE_FP_REGISTERS f24, f25, f26, f27, f28, f29, f30, f31
#elif V8_TARGET_ARCH_PPC64
// ===========================================================================
@ -124,14 +100,13 @@ namespace {
#define STACK_SHADOW_WORDS 14
#endif
#define PARAM_REGISTERS r3, r4, r5, r6, r7, r8, r9, r10
#define CALLEE_SAVE_REGISTERS \
r14.bit() | r15.bit() | r16.bit() | r17.bit() | r18.bit() | r19.bit() | \
r20.bit() | r21.bit() | r22.bit() | r23.bit() | r24.bit() | r25.bit() | \
r26.bit() | r27.bit() | r28.bit() | r29.bit() | r30.bit()
#define CALLEE_SAVE_FP_REGISTERS \
d14.bit() | d15.bit() | d16.bit() | d17.bit() | d18.bit() | d19.bit() | \
d20.bit() | d21.bit() | d22.bit() | d23.bit() | d24.bit() | d25.bit() | \
d26.bit() | d27.bit() | d28.bit() | d29.bit() | d30.bit() | d31.bit()
#define CALLEE_SAVE_REGISTERS \
r14, r15, r16, r17, r18, r19, r20, r21, r22, r23, r24, r25, r26, r27, r28, \
r29, r30
#define CALLEE_SAVE_FP_REGISTERS \
d14, d15, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, \
d29, d30, d31
#elif V8_TARGET_ARCH_S390X
// ===========================================================================
@ -139,11 +114,8 @@ namespace {
// ===========================================================================
#define STACK_SHADOW_WORDS 20
#define PARAM_REGISTERS r2, r3, r4, r5, r6
#define CALLEE_SAVE_REGISTERS \
r6.bit() | r7.bit() | r8.bit() | r9.bit() | r10.bit() | ip.bit() | r13.bit()
#define CALLEE_SAVE_FP_REGISTERS \
d8.bit() | d9.bit() | d10.bit() | d11.bit() | d12.bit() | d13.bit() | \
d14.bit() | d15.bit()
#define CALLEE_SAVE_REGISTERS r6, r7, r8, r9, r10, ip, r13
#define CALLEE_SAVE_FP_REGISTERS d8, d9, d10, d11, d12, d13, d14, d15
#elif V8_TARGET_ARCH_RISCV64
// ===========================================================================
@ -152,12 +124,9 @@ namespace {
#define PARAM_REGISTERS a0, a1, a2, a3, a4, a5, a6, a7
// fp is not part of CALLEE_SAVE_REGISTERS (similar to how MIPS64 or PPC defines
// it)
#define CALLEE_SAVE_REGISTERS \
s1.bit() | s2.bit() | s3.bit() | s4.bit() | s5.bit() | s6.bit() | s7.bit() | \
s8.bit() | s9.bit() | s10.bit() | s11.bit()
#define CALLEE_SAVE_FP_REGISTERS \
fs0.bit() | fs1.bit() | fs2.bit() | fs3.bit() | fs4.bit() | fs5.bit() | \
fs6.bit() | fs7.bit() | fs8.bit() | fs9.bit() | fs10.bit() | fs11.bit()
#define CALLEE_SAVE_REGISTERS s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11
#define CALLEE_SAVE_FP_REGISTERS \
fs0, fs1, fs2, fs3, fs4, fs5, fs6, fs7, fs8, fs9, fs10, fs11
#else
// ===========================================================================
// == unknown ================================================================
@ -318,17 +287,8 @@ CallDescriptor* Linkage::GetSimplifiedCDescriptor(Zone* zone,
BuildParameterLocations(msig, kFPParamRegisterCount, kParamRegisterCount,
kFPParamRegisters, kParamRegisters, &locations);
#ifdef CALLEE_SAVE_REGISTERS
const RegList kCalleeSaveRegisters = CALLEE_SAVE_REGISTERS;
#else
const RegList kCalleeSaveRegisters = 0;
#endif
#ifdef CALLEE_SAVE_FP_REGISTERS
const RegList kCalleeSaveFPRegisters = CALLEE_SAVE_FP_REGISTERS;
#else
const RegList kCalleeSaveFPRegisters = 0;
#endif
const RegList kCalleeSaveRegisters = {CALLEE_SAVE_REGISTERS};
const DoubleRegList kCalleeSaveFPRegisters = {CALLEE_SAVE_FP_REGISTERS};
// The target for C calls is always an address (i.e. machine pointer).
MachineType target_type = MachineType::Pointer();

View File

@ -372,7 +372,7 @@ CallDescriptor* Linkage::GetCEntryStubCallDescriptor(
js_parameter_count, // stack_parameter_count
properties, // properties
kNoCalleeSaved, // callee-saved
kNoCalleeSaved, // callee-saved fp
kNoCalleeSavedFp, // callee-saved fp
flags, // flags
debug_name, // debug name
stack_order); // stack order
@ -426,7 +426,7 @@ CallDescriptor* Linkage::GetJSCallDescriptor(Zone* zone, bool is_osr,
js_parameter_count, // stack_parameter_count
Operator::kNoProperties, // properties
kNoCalleeSaved, // callee-saved
kNoCalleeSaved, // callee-saved fp
kNoCalleeSavedFp, // callee-saved fp
flags, // flags
"js-call"); // debug name
}
@ -522,7 +522,7 @@ CallDescriptor* Linkage::GetStubCallDescriptor(
RegList callee_saved_registers = kNoCalleeSaved;
if (descriptor.CalleeSaveRegisters()) {
callee_saved_registers = allocatable_registers;
DCHECK(callee_saved_registers);
DCHECK(!callee_saved_registers.is_empty());
}
LinkageLocation target_loc = LinkageLocation::ForAnyRegister(target_type);
return zone->New<CallDescriptor>( // --
@ -533,7 +533,7 @@ CallDescriptor* Linkage::GetStubCallDescriptor(
stack_parameter_count, // stack_parameter_count
properties, // properties
callee_saved_registers, // callee-saved registers
kNoCalleeSaved, // callee-saved fp
kNoCalleeSavedFp, // callee-saved fp
CallDescriptor::kCanUseRoots | flags, // flags
descriptor.DebugName(), // debug name
descriptor.GetStackArgumentOrder(), // stack order
@ -583,7 +583,7 @@ CallDescriptor* Linkage::GetBytecodeDispatchCallDescriptor(
stack_parameter_count, // stack_parameter_count
Operator::kNoProperties, // properties
kNoCalleeSaved, // callee-saved registers
kNoCalleeSaved, // callee-saved fp
kNoCalleeSavedFp, // callee-saved fp
kFlags, // flags
descriptor.DebugName());
}

View File

@ -36,7 +36,8 @@ class OptimizedCompilationInfo;
namespace compiler {
const RegList kNoCalleeSaved = 0;
constexpr RegList kNoCalleeSaved;
constexpr DoubleRegList kNoCalleeSavedFp;
class OsrHelper;
@ -253,13 +254,13 @@ class V8_EXPORT_PRIVATE CallDescriptor final
LocationSignature* location_sig, size_t param_slot_count,
Operator::Properties properties,
RegList callee_saved_registers,
RegList callee_saved_fp_registers, Flags flags,
DoubleRegList callee_saved_fp_registers, Flags flags,
const char* debug_name = "",
StackArgumentOrder stack_order = StackArgumentOrder::kDefault,
#if V8_ENABLE_WEBASSEMBLY
const wasm::FunctionSig* wasm_sig = nullptr,
#endif
const RegList allocatable_registers = 0,
const RegList allocatable_registers = {},
size_t return_slot_count = 0)
: kind_(kind),
target_type_(target_type),
@ -414,7 +415,9 @@ class V8_EXPORT_PRIVATE CallDescriptor final
RegList CalleeSavedRegisters() const { return callee_saved_registers_; }
// Get the callee-saved FP registers, if any, across this call.
RegList CalleeSavedFPRegisters() const { return callee_saved_fp_registers_; }
DoubleRegList CalleeSavedFPRegisters() const {
return callee_saved_fp_registers_;
}
const char* debug_name() const { return debug_name_; }
@ -443,7 +446,7 @@ class V8_EXPORT_PRIVATE CallDescriptor final
RegList AllocatableRegisters() const { return allocatable_registers_; }
bool HasRestrictedAllocatableRegisters() const {
return allocatable_registers_ != 0;
return !allocatable_registers_.is_empty();
}
EncodedCSignature ToEncodedCSignature() const;
@ -461,7 +464,7 @@ class V8_EXPORT_PRIVATE CallDescriptor final
const size_t return_slot_count_;
const Operator::Properties properties_;
const RegList callee_saved_registers_;
const RegList callee_saved_fp_registers_;
const DoubleRegList callee_saved_fp_registers_;
// Non-zero value means restricting the set of allocatable registers for
// register allocator to use.
const RegList allocatable_registers_;

View File

@ -503,7 +503,7 @@ class PipelineData {
if (call_descriptor && call_descriptor->RequiresFrameAsIncoming()) {
sequence_->instruction_blocks()[0]->mark_needs_frame();
} else {
DCHECK_EQ(0u, call_descriptor->CalleeSavedFPRegisters());
DCHECK(call_descriptor->CalleeSavedFPRegisters().is_empty());
}
}
@ -3474,7 +3474,7 @@ bool PipelineImpl::SelectInstructions(Linkage* linkage) {
if (call_descriptor->HasRestrictedAllocatableRegisters()) {
RegList registers = call_descriptor->AllocatableRegisters();
DCHECK_LT(0, NumRegs(registers));
DCHECK_LT(0, registers.Count());
restricted_config.reset(
RegisterConfiguration::RestrictGeneralRegisters(registers));
config = restricted_config.get();

View File

@ -8606,8 +8606,8 @@ CallDescriptor* GetWasmCallDescriptor(Zone* zone, const wasm::FunctionSig* fsig,
int return_slots = rets.NumStackSlots();
const RegList kCalleeSaveRegisters = 0;
const RegList kCalleeSaveFPRegisters = 0;
const RegList kCalleeSaveRegisters;
const DoubleRegList kCalleeSaveFPRegisters;
// The target for wasm calls is always a code object.
MachineType target_type = MachineType::Pointer();
@ -8639,7 +8639,7 @@ CallDescriptor* GetWasmCallDescriptor(Zone* zone, const wasm::FunctionSig* fsig,
"wasm-call", // debug name
StackArgumentOrder::kDefault, // order of the arguments in the stack
fsig, // signature
0, // allocatable registers
RegList{}, // allocatable registers
return_slots); // return slot count
}

View File

@ -7,7 +7,7 @@
#include "src/base/bits.h"
#include "src/base/macros.h"
#include "src/codegen/arm/register-arm.h"
#include "src/codegen/register.h"
#include "src/execution/frame-constants.h"
namespace v8 {
@ -77,17 +77,15 @@ class WasmCompileLazyFrameConstants : public TypedFrameConstants {
class WasmDebugBreakFrameConstants : public TypedFrameConstants {
public:
// r10: root, r11: fp, r12: ip, r13: sp, r14: lr, r15: pc.
static constexpr RegList kPushedGpRegs =
Register::ListOf(r0, r1, r2, r3, r4, r5, r6, r7, r8, r9);
static constexpr RegList kPushedGpRegs = {r0, r1, r2, r3, r4,
r5, r6, r7, r8, r9};
// d13: zero, d14-d15: scratch
static constexpr RegList kPushedFpRegs = LowDwVfpRegister::ListOf(
d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12);
static constexpr DoubleRegList kPushedFpRegs = {d0, d1, d2, d3, d4, d5, d6,
d7, d8, d9, d10, d11, d12};
static constexpr int kNumPushedGpRegisters =
base::bits::CountPopulation(kPushedGpRegs);
static constexpr int kNumPushedFpRegisters =
base::bits::CountPopulation(kPushedFpRegs);
static constexpr int kNumPushedGpRegisters = kPushedGpRegs.Count();
static constexpr int kNumPushedFpRegisters = kPushedFpRegs.Count();
static constexpr int kLastPushedGpRegisterOffset =
-TypedFrameConstants::kFixedFrameSizeFromFp -
@ -97,15 +95,17 @@ class WasmDebugBreakFrameConstants : public TypedFrameConstants {
// Offsets are fp-relative.
static int GetPushedGpRegisterOffset(int reg_code) {
DCHECK_NE(0, kPushedGpRegs & (1 << reg_code));
uint32_t lower_regs = kPushedGpRegs & ((uint32_t{1} << reg_code) - 1);
DCHECK_NE(0, kPushedGpRegs.bits() & (1 << reg_code));
uint32_t lower_regs =
kPushedGpRegs.bits() & ((uint32_t{1} << reg_code) - 1);
return kLastPushedGpRegisterOffset +
base::bits::CountPopulation(lower_regs) * kSystemPointerSize;
}
static int GetPushedFpRegisterOffset(int reg_code) {
DCHECK_NE(0, kPushedFpRegs & (1 << reg_code));
uint32_t lower_regs = kPushedFpRegs & ((uint32_t{1} << reg_code) - 1);
DCHECK_NE(0, kPushedFpRegs.bits() & (1 << reg_code));
uint32_t lower_regs =
kPushedFpRegs.bits() & ((uint32_t{1} << reg_code) - 1);
return kLastPushedFpRegisterOffset +
base::bits::CountPopulation(lower_regs) * kDoubleSize;
}

View File

@ -7,7 +7,6 @@
#include "src/base/bits.h"
#include "src/base/macros.h"
#include "src/codegen/arm64/register-arm64.h"
#include "src/codegen/register.h"
#include "src/codegen/reglist.h"
#include "src/common/globals.h"
@ -98,23 +97,21 @@ class WasmDebugBreakFrameConstants : public TypedFrameConstants {
public:
// x16: ip0, x17: ip1, x18: platform register, x26: root, x28: base, x29: fp,
// x30: lr, x31: xzr.
static constexpr RegList kPushedGpRegs = CPURegister::ListOf(
x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x19,
x20, x21, x22, x23, x24, x25, x27);
static constexpr RegList kPushedGpRegs = {
x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11,
x12, x13, x14, x15, x19, x20, x21, x22, x23, x24, x25, x27};
// We push FpRegs as 128-bit SIMD registers, so 16-byte frame alignment
// is guaranteed regardless of register count.
static constexpr RegList kPushedFpRegs = CPURegister::ListOf(
d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d16, d17,
d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29);
static constexpr DoubleRegList kPushedFpRegs = {
d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14,
d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29};
static constexpr int kNumPushedGpRegisters =
base::bits::CountPopulation(kPushedGpRegs);
static constexpr int kNumPushedGpRegisters = kPushedGpRegs.Count();
static_assert(kNumPushedGpRegisters % 2 == 0,
"stack frames need to be 16-byte aligned");
static constexpr int kNumPushedFpRegisters =
base::bits::CountPopulation(kPushedFpRegs);
static constexpr int kNumPushedFpRegisters = kPushedFpRegs.Count();
static constexpr int kLastPushedGpRegisterOffset =
// Header is padded to 16 byte (see {MacroAssembler::EnterFrame}).
@ -125,15 +122,17 @@ class WasmDebugBreakFrameConstants : public TypedFrameConstants {
// Offsets are fp-relative.
static int GetPushedGpRegisterOffset(int reg_code) {
DCHECK_NE(0, kPushedGpRegs & (1 << reg_code));
uint32_t lower_regs = kPushedGpRegs & ((uint32_t{1} << reg_code) - 1);
DCHECK_NE(0, kPushedGpRegs.bits() & (1 << reg_code));
uint32_t lower_regs =
kPushedGpRegs.bits() & ((uint32_t{1} << reg_code) - 1);
return kLastPushedGpRegisterOffset +
base::bits::CountPopulation(lower_regs) * kSystemPointerSize;
}
static int GetPushedFpRegisterOffset(int reg_code) {
DCHECK_NE(0, kPushedFpRegs & (1 << reg_code));
uint32_t lower_regs = kPushedFpRegs & ((uint32_t{1} << reg_code) - 1);
DCHECK_NE(0, kPushedFpRegs.bits() & (1 << reg_code));
uint32_t lower_regs =
kPushedFpRegs.bits() & ((uint32_t{1} << reg_code) - 1);
return kLastPushedFpRegisterOffset +
base::bits::CountPopulation(lower_regs) * kSimd128Size;
}

View File

@ -187,7 +187,7 @@ int PopLowestIndexAsCode(CPURegList* list) {
if (list->IsEmpty()) {
return -1;
}
RegList reg_list = list->list();
uint64_t reg_list = list->bits();
int index = base::bits::CountTrailingZeros(reg_list);
DCHECK((1LL << index) & reg_list);
list->Remove(index);

Some files were not shown because too many files have changed in this diff Show More