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:
parent
46000a1244
commit
6aafc43e9d
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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));
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user