Extract calling RecordWrite CSA logic to a function

There are two places where RecordWrite code stub is called,
OutOfLineRecordWrite and RecordWriteField. With this commit, if
`v8_enable_csa_write_barrier` flag is turned on, no instances of the old
RecordWrite stub appear in the snapshot.

Bug: chromium:749486
Change-Id: I2bc3fa38c8831736303b46d153a79c034a450f16
Reviewed-on: https://chromium-review.googlesource.com/648983
Commit-Queue: Albert Mingkun Yang <albertnetymk@google.com>
Reviewed-by: Jaroslav Sevcik <jarin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48004}
This commit is contained in:
Albert Mingkun Yang 2017-09-13 14:21:06 +02:00 committed by Commit Bot
parent 46000a1244
commit 6aafc43e9d
24 changed files with 565 additions and 292 deletions

View File

@ -11,6 +11,7 @@
#include "src/base/division-by-constant.h"
#include "src/base/utils/random-number-generator.h"
#include "src/bootstrapper.h"
#include "src/callable.h"
#include "src/codegen.h"
#include "src/counters.h"
#include "src/debug/debug.h"
@ -549,6 +550,63 @@ void MacroAssembler::RecordWriteField(
}
}
void TurboAssembler::SaveRegisters(RegList registers) {
DCHECK(NumRegs(registers) > 0);
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);
}
void TurboAssembler::RestoreRegisters(RegList registers) {
DCHECK(NumRegs(registers) > 0);
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);
}
void TurboAssembler::CallRecordWriteStub(
Register object, Register address,
RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode) {
// TODO(albertnetymk): For now we ignore remembered_set_action and fp_mode,
// i.e. always emit remember set and save FP registers in RecordWriteStub. If
// large performance regression is observed, we should use these values to
// avoid unnecessary work.
Callable const callable =
Builtins::CallableFor(isolate(), Builtins::kRecordWrite);
RegList registers = callable.descriptor().allocatable_registers();
SaveRegisters(registers);
Register object_parameter(callable.descriptor().GetRegisterParameter(
RecordWriteDescriptor::kObject));
Register slot_parameter(
callable.descriptor().GetRegisterParameter(RecordWriteDescriptor::kSlot));
Register isolate_parameter(callable.descriptor().GetRegisterParameter(
RecordWriteDescriptor::kIsolate));
Push(object);
Push(address);
Pop(slot_parameter);
Pop(object_parameter);
Move(isolate_parameter,
Operand(ExternalReference::isolate_address(isolate())));
Call(callable.code(), RelocInfo::CODE_TARGET);
RestoreRegisters(registers);
}
// Will clobber 3 registers: object, map and dst. The register 'object' contains
// a heap object pointer. A scratch register also needs to be available.
void MacroAssembler::RecordWriteForMap(Register object,
@ -675,9 +733,13 @@ void MacroAssembler::RecordWrite(
if (lr_status == kLRHasNotBeenSaved) {
push(lr);
}
#ifdef V8_CSA_WRITE_BARRIER
CallRecordWriteStub(object, address, remembered_set_action, fp_mode);
#else
RecordWriteStub stub(isolate(), object, value, address, remembered_set_action,
fp_mode);
CallStub(&stub);
#endif
if (lr_status == kLRHasNotBeenSaved) {
pop(lr);
}

View File

@ -393,6 +393,13 @@ class TurboAssembler : public Assembler {
// Z condition flag: Z==0 if d16-d31 available, Z==1 otherwise.
void CheckFor32DRegs(Register scratch);
void SaveRegisters(RegList registers);
void RestoreRegisters(RegList registers);
void CallRecordWriteStub(Register object, Register address,
RememberedSetAction remembered_set_action,
SaveFPRegsMode fp_mode);
// Does a runtime check for 16/32 FP registers. Either way, pushes 32 double
// values to location, saving [d0..(d15|d31)].
void SaveFPRegs(Register location, Register scratch);

View File

@ -8,6 +8,7 @@
#include "src/base/bits.h"
#include "src/base/division-by-constant.h"
#include "src/bootstrapper.h"
#include "src/callable.h"
#include "src/codegen.h"
#include "src/debug/debug.h"
#include "src/external-reference-table.h"
@ -3155,6 +3156,62 @@ void MacroAssembler::RecordWriteField(
}
}
void TurboAssembler::SaveRegisters(RegList registers) {
DCHECK(NumRegs(registers) > 0);
CPURegList regs(lr);
for (int i = 0; i < Register::kNumRegisters; ++i) {
if ((registers >> i) & 1u) {
regs.Combine(Register::XRegFromCode(i));
}
}
PushCPURegList(regs);
}
void TurboAssembler::RestoreRegisters(RegList registers) {
DCHECK(NumRegs(registers) > 0);
CPURegList regs(lr);
for (int i = 0; i < Register::kNumRegisters; ++i) {
if ((registers >> i) & 1u) {
regs.Combine(Register::XRegFromCode(i));
}
}
PopCPURegList(regs);
}
void TurboAssembler::CallRecordWriteStub(
Register object, Register address,
RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode) {
// TODO(albertnetymk): For now we ignore remembered_set_action and fp_mode,
// i.e. always emit remember set and save FP registers in RecordWriteStub. If
// large performance regression is observed, we should use these values to
// avoid unnecessary work.
Callable const callable =
Builtins::CallableFor(isolate(), Builtins::kRecordWrite);
RegList registers = callable.descriptor().allocatable_registers();
SaveRegisters(registers);
Register object_parameter(callable.descriptor().GetRegisterParameter(
RecordWriteDescriptor::kObject));
Register slot_parameter(
callable.descriptor().GetRegisterParameter(RecordWriteDescriptor::kSlot));
Register isolate_parameter(callable.descriptor().GetRegisterParameter(
RecordWriteDescriptor::kIsolate));
Push(object);
Push(address);
Pop(slot_parameter);
Pop(object_parameter);
Mov(isolate_parameter, ExternalReference::isolate_address(isolate()));
Call(callable.code(), RelocInfo::CODE_TARGET);
RestoreRegisters(registers);
}
// Will clobber: object, map, dst.
// If lr_status is kLRHasBeenSaved, lr will also be clobbered.
@ -3278,9 +3335,13 @@ void MacroAssembler::RecordWrite(
if (lr_status == kLRHasNotBeenSaved) {
Push(padreg, lr);
}
#ifdef V8_CSA_WRITE_BARRIER
CallRecordWriteStub(object, address, remembered_set_action, fp_mode);
#else
RecordWriteStub stub(isolate(), object, value, address, remembered_set_action,
fp_mode);
CallStub(&stub);
#endif
if (lr_status == kLRHasNotBeenSaved) {
Pop(lr, padreg);
}

View File

@ -781,6 +781,13 @@ class TurboAssembler : public Assembler {
inline void push(Register src) { Push(src); }
inline void pop(Register dst) { Pop(dst); }
void SaveRegisters(RegList registers);
void RestoreRegisters(RegList registers);
void CallRecordWriteStub(Register object, Register address,
RememberedSetAction remembered_set_action,
SaveFPRegsMode fp_mode);
// Alternative forms of Push and Pop, taking a RegList or CPURegList that
// specifies the registers that are to be pushed or popped. Higher-numbered
// registers are associated with higher memory addresses (as in the A32 push

View File

@ -7,7 +7,6 @@
#include "src/arm/macro-assembler-arm.h"
#include "src/assembler-inl.h"
#include "src/boxed-float.h"
#include "src/callable.h"
#include "src/compilation-info.h"
#include "src/compiler/code-generator-impl.h"
#include "src/compiler/gap-resolver.h"
@ -216,29 +215,6 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
unwinding_info_writer_(unwinding_info_writer),
zone_(gen->zone()) {}
void SaveRegisters(RegList registers) {
DCHECK(NumRegs(registers) > 0);
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 | lr.bit());
}
void RestoreRegisters(RegList registers) {
DCHECK(NumRegs(registers) > 0);
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 | lr.bit());
}
void Generate() final {
if (mode_ > RecordWriteMode::kValueIsPointer) {
__ JumpIfSmi(value_, exit());
@ -252,34 +228,6 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
DCHECK_EQ(0, index_immediate_);
__ add(scratch1_, object_, Operand(index_));
}
#ifdef V8_CSA_WRITE_BARRIER
Callable const callable =
Builtins::CallableFor(__ isolate(), Builtins::kRecordWrite);
RegList registers = callable.descriptor().allocatable_registers();
unwinding_info_writer_->MarkLinkRegisterOnTopOfStack(__ pc_offset());
SaveRegisters(registers);
Register object_parameter(callable.descriptor().GetRegisterParameter(
RecordWriteDescriptor::kObject));
Register slot_parameter(callable.descriptor().GetRegisterParameter(
RecordWriteDescriptor::kSlot));
Register isolate_parameter(callable.descriptor().GetRegisterParameter(
RecordWriteDescriptor::kIsolate));
__ Push(object_);
__ Push(scratch1_);
__ Pop(slot_parameter);
__ Pop(object_parameter);
__ Move(isolate_parameter,
Operand(ExternalReference::isolate_address(__ isolate())));
__ Call(callable.code(), RelocInfo::CODE_TARGET);
RestoreRegisters(registers);
unwinding_info_writer_->MarkPopLinkRegisterFromTopOfStack(__ pc_offset());
#else
RememberedSetAction const remembered_set_action =
mode_ > RecordWriteMode::kValueIsMap ? EMIT_REMEMBERED_SET
: OMIT_REMEMBERED_SET;
@ -290,14 +238,18 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
__ Push(lr);
unwinding_info_writer_->MarkLinkRegisterOnTopOfStack(__ pc_offset());
}
#ifdef V8_CSA_WRITE_BARRIER
__ CallRecordWriteStub(object_, scratch1_, remembered_set_action,
save_fp_mode);
#else
__ CallStubDelayed(
new (zone_) RecordWriteStub(nullptr, object_, scratch0_, scratch1_,
remembered_set_action, save_fp_mode));
#endif
if (must_save_lr_) {
__ Pop(lr);
unwinding_info_writer_->MarkPopLinkRegisterFromTopOfStack(__ pc_offset());
}
#endif
}
private:

View File

@ -6,7 +6,6 @@
#include "src/arm64/assembler-arm64-inl.h"
#include "src/arm64/macro-assembler-arm64-inl.h"
#include "src/callable.h"
#include "src/compilation-info.h"
#include "src/compiler/code-generator-impl.h"
#include "src/compiler/gap-resolver.h"
@ -322,30 +321,6 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
unwinding_info_writer_(unwinding_info_writer),
zone_(gen->zone()) {}
void SaveRegisters(RegList registers) {
DCHECK(NumRegs(registers) > 0);
CPURegList regs(lr);
for (int i = 0; i < Register::kNumRegisters; ++i) {
if ((registers >> i) & 1u) {
regs.Combine(Register::XRegFromCode(i));
}
}
__ PushCPURegList(regs);
}
void RestoreRegisters(RegList registers) {
DCHECK(NumRegs(registers) > 0);
CPURegList regs(lr);
for (int i = 0; i < Register::kNumRegisters; ++i) {
if ((registers >> i) & 1u) {
regs.Combine(Register::XRegFromCode(i));
}
}
__ PopCPURegList(regs);
}
void Generate() final {
if (mode_ > RecordWriteMode::kValueIsPointer) {
__ JumpIfSmi(value_, exit());
@ -354,34 +329,6 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
MemoryChunk::kPointersToHereAreInterestingMask,
exit());
__ Add(scratch1_, object_, index_);
#ifdef V8_CSA_WRITE_BARRIER
Callable const callable =
Builtins::CallableFor(__ isolate(), Builtins::kRecordWrite);
RegList registers = callable.descriptor().allocatable_registers();
SaveRegisters(registers);
unwinding_info_writer_->MarkLinkRegisterOnTopOfStack(__ pc_offset(),
__ StackPointer());
Register object_parameter(callable.descriptor().GetRegisterParameter(
RecordWriteDescriptor::kObject));
Register slot_parameter(callable.descriptor().GetRegisterParameter(
RecordWriteDescriptor::kSlot));
Register isolate_parameter(callable.descriptor().GetRegisterParameter(
RecordWriteDescriptor::kIsolate));
__ Push(object_);
__ Push(scratch1_);
__ Pop(slot_parameter);
__ Pop(object_parameter);
__ Mov(isolate_parameter, ExternalReference::isolate_address(__ isolate()));
__ Call(callable.code(), RelocInfo::CODE_TARGET);
RestoreRegisters(registers);
unwinding_info_writer_->MarkPopLinkRegisterFromTopOfStack(__ pc_offset());
#else
RememberedSetAction const remembered_set_action =
mode_ > RecordWriteMode::kValueIsMap ? EMIT_REMEMBERED_SET
: OMIT_REMEMBERED_SET;
@ -393,14 +340,18 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
unwinding_info_writer_->MarkLinkRegisterOnTopOfStack(__ pc_offset(),
__ StackPointer());
}
#ifdef V8_CSA_WRITE_BARRIER
__ CallRecordWriteStub(object_, scratch1_, remembered_set_action,
save_fp_mode);
#else
__ CallStubDelayed(
new (zone_) RecordWriteStub(nullptr, object_, scratch0_, scratch1_,
remembered_set_action, save_fp_mode));
#endif
if (must_save_lr_) {
__ Pop(lr);
unwinding_info_writer_->MarkPopLinkRegisterFromTopOfStack(__ pc_offset());
}
#endif
}
private:

View File

@ -282,37 +282,15 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
MemoryChunk::kPointersToHereAreInterestingMask, zero,
exit());
__ lea(scratch1_, operand_);
#ifdef V8_CSA_WRITE_BARRIER
Callable const callable =
Builtins::CallableFor(__ isolate(), Builtins::kRecordWrite);
RegList registers = callable.descriptor().allocatable_registers();
SaveRegisters(registers);
Register object_parameter(callable.descriptor().GetRegisterParameter(
RecordWriteDescriptor::kObject));
Register slot_parameter(callable.descriptor().GetRegisterParameter(
RecordWriteDescriptor::kSlot));
Register isolate_parameter(callable.descriptor().GetRegisterParameter(
RecordWriteDescriptor::kIsolate));
__ push(object_);
__ push(scratch1_);
__ pop(slot_parameter);
__ pop(object_parameter);
__ mov(isolate_parameter,
Immediate(ExternalReference::isolate_address(__ isolate())));
__ Call(callable.code(), RelocInfo::CODE_TARGET);
RestoreRegisters(registers);
#else
RememberedSetAction const remembered_set_action =
mode_ > RecordWriteMode::kValueIsMap ? EMIT_REMEMBERED_SET
: OMIT_REMEMBERED_SET;
SaveFPRegsMode const save_fp_mode =
frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs;
#ifdef V8_CSA_WRITE_BARRIER
__ CallRecordWriteStub(object_, scratch1_, remembered_set_action,
save_fp_mode);
#else
__ CallStubDelayed(
new (zone_) RecordWriteStub(nullptr, object_, scratch0_, scratch1_,
remembered_set_action, save_fp_mode));

View File

@ -264,31 +264,6 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
MemoryChunk::kPointersToHereAreInterestingMask, eq,
exit());
__ Addu(scratch1_, object_, index_);
#ifdef V8_CSA_WRITE_BARRIER
Callable const callable =
Builtins::CallableFor(__ isolate(), Builtins::kRecordWrite);
RegList registers = callable.descriptor().allocatable_registers();
SaveRegisters(registers);
Register object_parameter(callable.descriptor().GetRegisterParameter(
RecordWriteDescriptor::kObject));
Register slot_parameter(callable.descriptor().GetRegisterParameter(
RecordWriteDescriptor::kSlot));
Register isolate_parameter(callable.descriptor().GetRegisterParameter(
RecordWriteDescriptor::kIsolate));
__ Push(object_);
__ Push(scratch1_);
__ Pop(slot_parameter);
__ Pop(object_parameter);
__ li(isolate_parameter,
Operand(ExternalReference::isolate_address(__ isolate())));
__ Call(callable.code(), RelocInfo::CODE_TARGET);
RestoreRegisters(registers);
#else
RememberedSetAction const remembered_set_action =
mode_ > RecordWriteMode::kValueIsMap ? EMIT_REMEMBERED_SET
: OMIT_REMEMBERED_SET;
@ -298,13 +273,17 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
// We need to save and restore ra if the frame was elided.
__ Push(ra);
}
#ifdef V8_CSA_WRITE_BARRIER
__ CallRecordWriteStub(object_, scratch1_, remembered_set_action,
save_fp_mode);
#else
__ CallStubDelayed(
new (zone_) RecordWriteStub(nullptr, object_, scratch0_, scratch1_,
remembered_set_action, save_fp_mode));
#endif
if (must_save_lr_) {
__ Pop(ra);
}
#endif
}
private:

View File

@ -264,31 +264,6 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
MemoryChunk::kPointersToHereAreInterestingMask, eq,
exit());
__ Daddu(scratch1_, object_, index_);
#ifdef V8_CSA_WRITE_BARRIER
Callable const callable =
Builtins::CallableFor(__ isolate(), Builtins::kRecordWrite);
RegList registers = callable.descriptor().allocatable_registers();
SaveRegisters(registers);
Register object_parameter(callable.descriptor().GetRegisterParameter(
RecordWriteDescriptor::kObject));
Register slot_parameter(callable.descriptor().GetRegisterParameter(
RecordWriteDescriptor::kSlot));
Register isolate_parameter(callable.descriptor().GetRegisterParameter(
RecordWriteDescriptor::kIsolate));
__ Push(object_);
__ Push(scratch1_);
__ Pop(slot_parameter);
__ Pop(object_parameter);
__ li(isolate_parameter,
Operand(ExternalReference::isolate_address(__ isolate())));
__ Call(callable.code(), RelocInfo::CODE_TARGET);
RestoreRegisters(registers);
#else
RememberedSetAction const remembered_set_action =
mode_ > RecordWriteMode::kValueIsMap ? EMIT_REMEMBERED_SET
: OMIT_REMEMBERED_SET;
@ -298,13 +273,17 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
// We need to save and restore ra if the frame was elided.
__ Push(ra);
}
#ifdef V8_CSA_WRITE_BARRIER
__ CallRecordWriteStub(object_, scratch1_, remembered_set_action,
save_fp_mode);
#else
__ CallStubDelayed(
new (zone_) RecordWriteStub(nullptr, object_, scratch0_, scratch1_,
remembered_set_action, save_fp_mode));
#endif
if (must_save_lr_) {
__ Pop(ra);
}
#endif
}
private:

View File

@ -4,7 +4,6 @@
#include "src/compiler/code-generator.h"
#include "src/callable.h"
#include "src/compilation-info.h"
#include "src/compiler/code-generator-impl.h"
#include "src/compiler/gap-resolver.h"
@ -225,39 +224,6 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
DCHECK_EQ(0, offset_immediate_);
__ add(scratch1_, object_, offset_);
}
#ifdef V8_CSA_WRITE_BARRIER
Callable const callable =
Builtins::CallableFor(__ isolate(), Builtins::kRecordWrite);
RegList registers = callable.descriptor().allocatable_registers();
if (FLAG_enable_embedded_constant_pool) {
registers |= kConstantPoolRegister.bit();
}
SaveRegisters(registers);
__ mflr(scratch0_);
__ Push(scratch0_);
Register object_parameter(callable.descriptor().GetRegisterParameter(
RecordWriteDescriptor::kObject));
Register slot_parameter(callable.descriptor().GetRegisterParameter(
RecordWriteDescriptor::kSlot));
Register isolate_parameter(callable.descriptor().GetRegisterParameter(
RecordWriteDescriptor::kIsolate));
__ push(object_);
__ push(scratch1_);
__ pop(slot_parameter);
__ pop(object_parameter);
__ mov(isolate_parameter,
Operand(ExternalReference::isolate_address(__ isolate())));
__ Call(callable.code(), RelocInfo::CODE_TARGET);
__ Pop(scratch0_);
__ mtlr(scratch0_);
RestoreRegisters(registers);
#else
RememberedSetAction const remembered_set_action =
mode_ > RecordWriteMode::kValueIsMap ? EMIT_REMEMBERED_SET
: OMIT_REMEMBERED_SET;
@ -268,6 +234,10 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
__ mflr(scratch0_);
__ Push(scratch0_);
}
#ifdef V8_CSA_WRITE_BARRIER
__ CallRecordWriteStub(object_, scratch1_, remembered_set_action,
save_fp_mode);
#else
if (must_save_lr_ && FLAG_enable_embedded_constant_pool) {
ConstantPoolUnavailableScope constant_pool_unavailable(tasm());
__ CallStubDelayed(
@ -278,12 +248,12 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
new (zone_) RecordWriteStub(nullptr, object_, scratch0_, scratch1_,
remembered_set_action, save_fp_mode));
}
#endif
if (must_save_lr_) {
// We need to save and restore lr if the frame was elided.
__ Pop(scratch0_);
__ mtlr(scratch0_);
}
#endif
}
private:

View File

@ -4,7 +4,6 @@
#include "src/compiler/code-generator.h"
#include "src/callable.h"
#include "src/compilation-info.h"
#include "src/compiler/code-generator-impl.h"
#include "src/compiler/gap-resolver.h"
@ -259,31 +258,6 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
DCHECK_EQ(0, offset_immediate_);
__ AddP(scratch1_, object_, offset_);
}
#ifdef V8_CSA_WRITE_BARRIER
Callable const callable =
Builtins::CallableFor(__ isolate(), Builtins::kRecordWrite);
RegList registers = callable.descriptor().allocatable_registers();
SaveRegisters(registers);
Register object_parameter(callable.descriptor().GetRegisterParameter(
RecordWriteDescriptor::kObject));
Register slot_parameter(callable.descriptor().GetRegisterParameter(
RecordWriteDescriptor::kSlot));
Register isolate_parameter(callable.descriptor().GetRegisterParameter(
RecordWriteDescriptor::kIsolate));
__ Push(object_);
__ Push(scratch1_);
__ Pop(slot_parameter);
__ Pop(object_parameter);
__ mov(isolate_parameter,
Operand(ExternalReference::isolate_address(__ isolate())));
__ Call(callable.code(), RelocInfo::CODE_TARGET);
RestoreRegisters(registers);
#else
RememberedSetAction const remembered_set_action =
mode_ > RecordWriteMode::kValueIsMap ? EMIT_REMEMBERED_SET
: OMIT_REMEMBERED_SET;
@ -293,14 +267,18 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
// We need to save and restore r14 if the frame was elided.
__ Push(r14);
}
#ifdef V8_CSA_WRITE_BARRIER
__ CallRecordWriteStub(object_, scratch1_, remembered_set_action,
save_fp_mode);
#else
__ CallStubDelayed(
new (zone_) RecordWriteStub(nullptr, object_, scratch0_, scratch1_,
remembered_set_action, save_fp_mode));
#endif
if (must_save_lr_) {
// We need to save and restore r14 if the frame was elided.
__ Pop(r14);
}
#endif
}
private:

View File

@ -6,7 +6,6 @@
#include <limits>
#include "src/callable.h"
#include "src/compilation-info.h"
#include "src/compiler/code-generator-impl.h"
#include "src/compiler/gap-resolver.h"
@ -242,24 +241,6 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
mode_(mode),
zone_(gen->zone()) {}
void SaveRegisters(RegList registers) {
DCHECK(NumRegs(registers) > 0);
for (int i = 0; i < Register::kNumRegisters; ++i) {
if ((registers >> i) & 1u) {
__ pushq(Register::from_code(i));
}
}
}
void RestoreRegisters(RegList registers) {
DCHECK(NumRegs(registers) > 0);
for (int i = Register::kNumRegisters - 1; i >= 0; --i) {
if ((registers >> i) & 1u) {
__ popq(Register::from_code(i));
}
}
}
void Generate() final {
if (mode_ > RecordWriteMode::kValueIsPointer) {
__ JumpIfSmi(value_, exit());
@ -269,38 +250,16 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
exit());
__ leap(scratch1_, operand_);
#ifdef V8_CSA_WRITE_BARRIER
Callable const callable =
Builtins::CallableFor(__ isolate(), Builtins::kRecordWrite);
RegList registers = callable.descriptor().allocatable_registers();
SaveRegisters(registers);
Register object_parameter(callable.descriptor().GetRegisterParameter(
RecordWriteDescriptor::kObject));
Register slot_parameter(callable.descriptor().GetRegisterParameter(
RecordWriteDescriptor::kSlot));
Register isolate_parameter(callable.descriptor().GetRegisterParameter(
RecordWriteDescriptor::kIsolate));
__ pushq(object_);
__ pushq(scratch1_);
__ popq(slot_parameter);
__ popq(object_parameter);
__ LoadAddress(isolate_parameter,
ExternalReference::isolate_address(__ isolate()));
__ Call(callable.code(), RelocInfo::CODE_TARGET);
RestoreRegisters(registers);
#else
RememberedSetAction const remembered_set_action =
mode_ > RecordWriteMode::kValueIsMap ? EMIT_REMEMBERED_SET
: OMIT_REMEMBERED_SET;
SaveFPRegsMode const save_fp_mode =
frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs;
#ifdef V8_CSA_WRITE_BARRIER
__ CallRecordWriteStub(object_, scratch1_, remembered_set_action,
save_fp_mode);
#else
__ CallStubDelayed(
new (zone_) RecordWriteStub(nullptr, object_, scratch0_, scratch1_,
remembered_set_action, save_fp_mode));

View File

@ -8,6 +8,7 @@
#include "src/base/division-by-constant.h"
#include "src/base/utils/random-number-generator.h"
#include "src/bootstrapper.h"
#include "src/callable.h"
#include "src/codegen.h"
#include "src/debug/debug.h"
#include "src/external-reference-table.h"
@ -318,7 +319,57 @@ void MacroAssembler::RecordWriteField(
}
}
void TurboAssembler::SaveRegisters(RegList registers) {
DCHECK(NumRegs(registers) > 0);
for (int i = 0; i < Register::kNumRegisters; ++i) {
if ((registers >> i) & 1u) {
push(Register::from_code(i));
}
}
}
void TurboAssembler::RestoreRegisters(RegList registers) {
DCHECK(NumRegs(registers) > 0);
for (int i = Register::kNumRegisters - 1; i >= 0; --i) {
if ((registers >> i) & 1u) {
pop(Register::from_code(i));
}
}
}
void TurboAssembler::CallRecordWriteStub(
Register object, Register address,
RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode) {
// TODO(albertnetymk): For now we ignore remembered_set_action and fp_mode,
// i.e. always emit remember set and save FP registers in RecordWriteStub. If
// large performance regression is observed, we should use these values to
// avoid unnecessary work.
Callable const callable =
Builtins::CallableFor(isolate(), Builtins::kRecordWrite);
RegList registers = callable.descriptor().allocatable_registers();
SaveRegisters(registers);
Register object_parameter(callable.descriptor().GetRegisterParameter(
RecordWriteDescriptor::kObject));
Register slot_parameter(
callable.descriptor().GetRegisterParameter(RecordWriteDescriptor::kSlot));
Register isolate_parameter(callable.descriptor().GetRegisterParameter(
RecordWriteDescriptor::kIsolate));
push(object);
push(address);
pop(slot_parameter);
pop(object_parameter);
mov(isolate_parameter,
Immediate(ExternalReference::isolate_address(isolate())));
Call(callable.code(), RelocInfo::CODE_TARGET);
RestoreRegisters(registers);
}
void MacroAssembler::RecordWriteForMap(
Register object,
Handle<Map> map,
@ -431,9 +482,13 @@ void MacroAssembler::RecordWrite(
&done,
Label::kNear);
#ifdef V8_CSA_WRITE_BARRIER
CallRecordWriteStub(object, address, remembered_set_action, fp_mode);
#else
RecordWriteStub stub(isolate(), object, value, address, remembered_set_action,
fp_mode);
CallStub(&stub);
#endif
bind(&done);

View File

@ -291,6 +291,13 @@ class TurboAssembler : public Assembler {
void Push(Handle<HeapObject> handle) { push(Immediate(handle)); }
void Push(Smi* smi) { Push(Immediate(smi)); }
void SaveRegisters(RegList registers);
void RestoreRegisters(RegList registers);
void CallRecordWriteStub(Register object, Register address,
RememberedSetAction remembered_set_action,
SaveFPRegsMode fp_mode);
// Calculate how much stack space (in bytes) are required to store caller
// registers excluding those specified in the arguments.
int RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode,

View File

@ -9,6 +9,7 @@
#include "src/base/bits.h"
#include "src/base/division-by-constant.h"
#include "src/bootstrapper.h"
#include "src/callable.h"
#include "src/codegen.h"
#include "src/debug/debug.h"
#include "src/external-reference-table.h"
@ -239,6 +240,59 @@ void MacroAssembler::RecordWriteField(
}
}
void TurboAssembler::SaveRegisters(RegList registers) {
DCHECK(NumRegs(registers) > 0);
RegList regs = 0;
for (int i = 0; i < Register::kNumRegisters; ++i) {
if ((registers >> i) & 1u) {
regs |= Register::from_code(i).bit();
}
}
MultiPush(regs);
}
void TurboAssembler::RestoreRegisters(RegList registers) {
DCHECK(NumRegs(registers) > 0);
RegList regs = 0;
for (int i = 0; i < Register::kNumRegisters; ++i) {
if ((registers >> i) & 1u) {
regs |= Register::from_code(i).bit();
}
}
MultiPop(regs);
}
void TurboAssembler::CallRecordWriteStub(
Register object, Register address,
RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode) {
// TODO(albertnetymk): For now we ignore remembered_set_action and fp_mode,
// i.e. always emit remember set and save FP registers in RecordWriteStub. If
// large performance regression is observed, we should use these values to
// avoid unnecessary work.
Callable const callable =
Builtins::CallableFor(isolate(), Builtins::kRecordWrite);
RegList registers = callable.descriptor().allocatable_registers();
SaveRegisters(registers);
Register object_parameter(callable.descriptor().GetRegisterParameter(
RecordWriteDescriptor::kObject));
Register slot_parameter(
callable.descriptor().GetRegisterParameter(RecordWriteDescriptor::kSlot));
Register isolate_parameter(callable.descriptor().GetRegisterParameter(
RecordWriteDescriptor::kIsolate));
Push(object);
Push(address);
Pop(slot_parameter);
Pop(object_parameter);
li(isolate_parameter, Operand(ExternalReference::isolate_address(isolate())));
Call(callable.code(), RelocInfo::CODE_TARGET);
RestoreRegisters(registers);
}
// Clobbers object, dst, map, and ra, if (ra_status == kRAHasBeenSaved)
void MacroAssembler::RecordWriteForMap(Register object,
@ -374,9 +428,13 @@ void MacroAssembler::RecordWrite(
if (ra_status == kRAHasNotBeenSaved) {
push(ra);
}
#ifdef V8_CSA_WRITE_BARRIER
CallRecordWriteStub(object, address, remembered_set_action, fp_mode);
#else
RecordWriteStub stub(isolate(), object, value, address, remembered_set_action,
fp_mode);
CallStub(&stub);
#endif
if (ra_status == kRAHasNotBeenSaved) {
pop(ra);
}

View File

@ -348,6 +348,13 @@ class TurboAssembler : public Assembler {
sw(src, MemOperand(sp, 0));
}
void SaveRegisters(RegList registers);
void RestoreRegisters(RegList registers);
void CallRecordWriteStub(Register object, Register address,
RememberedSetAction remembered_set_action,
SaveFPRegsMode fp_mode);
// Push multiple registers on the stack.
// Registers are saved in numerical order, with higher numbered registers
// saved in higher memory addresses.

View File

@ -9,6 +9,7 @@
#include "src/base/bits.h"
#include "src/base/division-by-constant.h"
#include "src/bootstrapper.h"
#include "src/callable.h"
#include "src/codegen.h"
#include "src/debug/debug.h"
#include "src/external-reference-table.h"
@ -239,6 +240,59 @@ void MacroAssembler::RecordWriteField(
}
}
void TurboAssembler::SaveRegisters(RegList registers) {
DCHECK(NumRegs(registers) > 0);
RegList regs = 0;
for (int i = 0; i < Register::kNumRegisters; ++i) {
if ((registers >> i) & 1u) {
regs |= Register::from_code(i).bit();
}
}
MultiPush(regs);
}
void TurboAssembler::RestoreRegisters(RegList registers) {
DCHECK(NumRegs(registers) > 0);
RegList regs = 0;
for (int i = 0; i < Register::kNumRegisters; ++i) {
if ((registers >> i) & 1u) {
regs |= Register::from_code(i).bit();
}
}
MultiPop(regs);
}
void TurboAssembler::CallRecordWriteStub(
Register object, Register address,
RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode) {
// TODO(albertnetymk): For now we ignore remembered_set_action and fp_mode,
// i.e. always emit remember set and save FP registers in RecordWriteStub. If
// large performance regression is observed, we should use these values to
// avoid unnecessary work.
Callable const callable =
Builtins::CallableFor(isolate(), Builtins::kRecordWrite);
RegList registers = callable.descriptor().allocatable_registers();
SaveRegisters(registers);
Register object_parameter(callable.descriptor().GetRegisterParameter(
RecordWriteDescriptor::kObject));
Register slot_parameter(
callable.descriptor().GetRegisterParameter(RecordWriteDescriptor::kSlot));
Register isolate_parameter(callable.descriptor().GetRegisterParameter(
RecordWriteDescriptor::kIsolate));
Push(object);
Push(address);
Pop(slot_parameter);
Pop(object_parameter);
li(isolate_parameter, Operand(ExternalReference::isolate_address(isolate())));
Call(callable.code(), RelocInfo::CODE_TARGET);
RestoreRegisters(registers);
}
// Clobbers object, dst, map, and ra, if (ra_status == kRAHasBeenSaved)
void MacroAssembler::RecordWriteForMap(Register object,
@ -374,9 +428,13 @@ void MacroAssembler::RecordWrite(
if (ra_status == kRAHasNotBeenSaved) {
push(ra);
}
#ifdef V8_CSA_WRITE_BARRIER
CallRecordWriteStub(object, address, remembered_set_action, fp_mode);
#else
RecordWriteStub stub(isolate(), object, value, address, remembered_set_action,
fp_mode);
CallStub(&stub);
#endif
if (ra_status == kRAHasNotBeenSaved) {
pop(ra);
}

View File

@ -390,6 +390,13 @@ class TurboAssembler : public Assembler {
Sd(src, MemOperand(sp, 0));
}
void SaveRegisters(RegList registers);
void RestoreRegisters(RegList registers);
void CallRecordWriteStub(Register object, Register address,
RememberedSetAction remembered_set_action,
SaveFPRegsMode fp_mode);
// Push multiple registers on the stack.
// Registers are saved in numerical order, with higher numbered registers
// saved in higher memory addresses.

View File

@ -10,6 +10,7 @@
#include "src/base/bits.h"
#include "src/base/division-by-constant.h"
#include "src/bootstrapper.h"
#include "src/callable.h"
#include "src/codegen.h"
#include "src/debug/debug.h"
#include "src/external-reference-table.h"
@ -366,6 +367,62 @@ void MacroAssembler::RecordWriteField(
}
}
void TurboAssembler::SaveRegisters(RegList registers) {
DCHECK(NumRegs(registers) > 0);
RegList regs = 0;
for (int i = 0; i < Register::kNumRegisters; ++i) {
if ((registers >> i) & 1u) {
regs |= Register::from_code(i).bit();
}
}
MultiPush(regs);
}
void TurboAssembler::RestoreRegisters(RegList registers) {
DCHECK(NumRegs(registers) > 0);
RegList regs = 0;
for (int i = 0; i < Register::kNumRegisters; ++i) {
if ((registers >> i) & 1u) {
regs |= Register::from_code(i).bit();
}
}
MultiPop(regs);
}
void TurboAssembler::CallRecordWriteStub(
Register object, Register address,
RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode) {
// TODO(albertnetymk): For now we ignore remembered_set_action and fp_mode,
// i.e. always emit remember set and save FP registers in RecordWriteStub. If
// large performance regression is observed, we should use these values to
// avoid unnecessary work.
Callable const callable =
Builtins::CallableFor(isolate(), Builtins::kRecordWrite);
RegList registers = callable.descriptor().allocatable_registers();
SaveRegisters(registers);
Register object_parameter(callable.descriptor().GetRegisterParameter(
RecordWriteDescriptor::kObject));
Register slot_parameter(
callable.descriptor().GetRegisterParameter(RecordWriteDescriptor::kSlot));
Register isolate_parameter(callable.descriptor().GetRegisterParameter(
RecordWriteDescriptor::kIsolate));
push(object);
push(address);
pop(slot_parameter);
pop(object_parameter);
mov(isolate_parameter,
Operand(ExternalReference::isolate_address(isolate())));
Call(callable.code(), RelocInfo::CODE_TARGET);
RestoreRegisters(registers);
}
// Will clobber 4 registers: object, map, dst, ip. The
// register 'object' contains a heap object pointer.
@ -478,9 +535,13 @@ void MacroAssembler::RecordWrite(
mflr(r0);
push(r0);
}
#ifdef V8_CSA_WRITE_BARRIER
CallRecordWriteStub(object, address, remembered_set_action, fp_mode);
#else
RecordWriteStub stub(isolate(), object, value, address, remembered_set_action,
fp_mode);
CallStub(&stub);
#endif
if (lr_status == kLRHasNotBeenSaved) {
pop(r0);
mtlr(r0);

View File

@ -312,6 +312,14 @@ class TurboAssembler : public Assembler {
LoadP(src1, MemOperand(sp, 4 * kPointerSize));
addi(sp, sp, Operand(5 * kPointerSize));
}
void SaveRegisters(RegList registers);
void RestoreRegisters(RegList registers);
void CallRecordWriteStub(Register object, Register address,
RememberedSetAction remembered_set_action,
SaveFPRegsMode fp_mode);
void MultiPush(RegList regs, Register location = sp);
void MultiPop(RegList regs, Register location = sp);

View File

@ -10,6 +10,7 @@
#include "src/base/bits.h"
#include "src/base/division-by-constant.h"
#include "src/bootstrapper.h"
#include "src/callable.h"
#include "src/codegen.h"
#include "src/debug/debug.h"
#include "src/external-reference-table.h"
@ -366,6 +367,61 @@ void MacroAssembler::RecordWriteField(
}
}
void TurboAssembler::SaveRegisters(RegList registers) {
DCHECK(NumRegs(registers) > 0);
RegList regs = 0;
for (int i = 0; i < Register::kNumRegisters; ++i) {
if ((registers >> i) & 1u) {
regs |= Register::from_code(i).bit();
}
}
MultiPush(regs);
}
void TurboAssembler::RestoreRegisters(RegList registers) {
DCHECK(NumRegs(registers) > 0);
RegList regs = 0;
for (int i = 0; i < Register::kNumRegisters; ++i) {
if ((registers >> i) & 1u) {
regs |= Register::from_code(i).bit();
}
}
MultiPop(regs);
}
void TurboAssembler::CallRecordWriteStub(
Register object, Register address,
RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode) {
// TODO(albertnetymk): For now we ignore remembered_set_action and fp_mode,
// i.e. always emit remember set and save FP registers in RecordWriteStub. If
// large performance regression is observed, we should use these values to
// avoid unnecessary work.
Callable const callable =
Builtins::CallableFor(isolate(), Builtins::kRecordWrite);
RegList registers = callable.descriptor().allocatable_registers();
SaveRegisters(registers);
Register object_parameter(callable.descriptor().GetRegisterParameter(
RecordWriteDescriptor::kObject));
Register slot_parameter(
callable.descriptor().GetRegisterParameter(RecordWriteDescriptor::kSlot));
Register isolate_parameter(callable.descriptor().GetRegisterParameter(
RecordWriteDescriptor::kIsolate));
Push(object);
Push(address);
Pop(slot_parameter);
Pop(object_parameter);
mov(isolate_parameter,
Operand(ExternalReference::isolate_address(isolate())));
Call(callable.code(), RelocInfo::CODE_TARGET);
RestoreRegisters(registers);
}
// Will clobber 4 registers: object, map, dst, ip. The
// register 'object' contains a heap object pointer.
void MacroAssembler::RecordWriteForMap(Register object, Register map,
@ -470,9 +526,13 @@ void MacroAssembler::RecordWrite(
if (lr_status == kLRHasNotBeenSaved) {
push(r14);
}
#ifdef V8_CSA_WRITE_BARRIER
CallRecordWriteStub(object, address, remembered_set_action, fp_mode);
#else
RecordWriteStub stub(isolate(), object, value, address, remembered_set_action,
fp_mode);
CallStub(&stub);
#endif
if (lr_status == kLRHasNotBeenSaved) {
pop(r14);
}

View File

@ -226,6 +226,13 @@ class TurboAssembler : public Assembler {
void Move(Register dst, Register src, Condition cond = al);
void Move(DoubleRegister dst, DoubleRegister src);
void SaveRegisters(RegList registers);
void RestoreRegisters(RegList registers);
void CallRecordWriteStub(Register object, Register address,
RememberedSetAction remembered_set_action,
SaveFPRegsMode fp_mode);
void MultiPush(RegList regs, Register location = sp);
void MultiPop(RegList regs, Register location = sp);

View File

@ -8,6 +8,7 @@
#include "src/base/division-by-constant.h"
#include "src/base/utils/random-number-generator.h"
#include "src/bootstrapper.h"
#include "src/callable.h"
#include "src/codegen.h"
#include "src/counters.h"
#include "src/debug/debug.h"
@ -296,6 +297,56 @@ void MacroAssembler::RecordWriteField(
}
}
void TurboAssembler::SaveRegisters(RegList registers) {
DCHECK(NumRegs(registers) > 0);
for (int i = 0; i < Register::kNumRegisters; ++i) {
if ((registers >> i) & 1u) {
pushq(Register::from_code(i));
}
}
}
void TurboAssembler::RestoreRegisters(RegList registers) {
DCHECK(NumRegs(registers) > 0);
for (int i = Register::kNumRegisters - 1; i >= 0; --i) {
if ((registers >> i) & 1u) {
popq(Register::from_code(i));
}
}
}
void TurboAssembler::CallRecordWriteStub(
Register object, Register address,
RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode) {
// TODO(albertnetymk): For now we ignore remembered_set_action and fp_mode,
// i.e. always emit remember set and save FP registers in RecordWriteStub. If
// large performance regression is observed, we should use these values to
// avoid unnecessary work.
Callable const callable =
Builtins::CallableFor(isolate(), Builtins::kRecordWrite);
RegList registers = callable.descriptor().allocatable_registers();
SaveRegisters(registers);
Register object_parameter(callable.descriptor().GetRegisterParameter(
RecordWriteDescriptor::kObject));
Register slot_parameter(
callable.descriptor().GetRegisterParameter(RecordWriteDescriptor::kSlot));
Register isolate_parameter(callable.descriptor().GetRegisterParameter(
RecordWriteDescriptor::kIsolate));
pushq(object);
pushq(address);
popq(slot_parameter);
popq(object_parameter);
LoadAddress(isolate_parameter, ExternalReference::isolate_address(isolate()));
Call(callable.code(), RelocInfo::CODE_TARGET);
RestoreRegisters(registers);
}
void MacroAssembler::RecordWriteForMap(Register object,
Register map,
@ -419,9 +470,13 @@ void MacroAssembler::RecordWrite(
&done,
Label::kNear);
#ifdef V8_CSA_WRITE_BARRIER
CallRecordWriteStub(object, address, remembered_set_action, fp_mode);
#else
RecordWriteStub stub(isolate(), object, value, address, remembered_set_action,
fp_mode);
CallStub(&stub);
#endif
bind(&done);

View File

@ -408,6 +408,13 @@ class TurboAssembler : public Assembler {
addp(kRootRegister, Immediate(kRootRegisterBias));
}
void SaveRegisters(RegList registers);
void RestoreRegisters(RegList registers);
void CallRecordWriteStub(Register object, Register address,
RememberedSetAction remembered_set_action,
SaveFPRegsMode fp_mode);
void MoveNumber(Register dst, double value);
void MoveNonSmi(Register dst, double value);