[sparkplug] Use separate WriteBarrier stubs
Inline the RememberedSetAction and SaveFPMode flags directly into the RecordWrite stubs: - Save two register for input arguments - Avoid branches in the RecordWrite stubs We end up with 2 stubs for the EphemeronKeyBarrier and 4 stubs for RecordWrite. Due to more inlined calls we have roughly 1KiB more builtins code for RecordWrite currently. We will address this in the future by splitting out common code into a separate stub. There is no additional code size overhead for EphemeronKeyBarrier. This saves 4 to 8 bytes on x64 per RecordWrite call and 2.5% sparkplug code size reduction on d3.min.js. Bug: v8:11420 Change-Id: Ib7170265dd6dd4b3aaf8275083f096e76fae8251 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2902731 Reviewed-by: Michael Lippautz <mlippautz@chromium.org> Reviewed-by: Leszek Swirski <leszeks@chromium.org> Reviewed-by: Andreas Haas <ahaas@chromium.org> Reviewed-by: Jakob Gruber <jgruber@chromium.org> Commit-Queue: Camillo Bruni <cbruni@chromium.org> Cr-Commit-Position: refs/heads/master@{#74661}
This commit is contained in:
parent
dac4a1e376
commit
2a43f8c4c7
@ -33,8 +33,12 @@ namespace internal {
|
||||
|
||||
#define BUILTIN_LIST_BASE(CPP, TFJ, TFC, TFS, TFH, ASM) \
|
||||
/* GC write barrirer */ \
|
||||
TFC(RecordWrite, RecordWrite) \
|
||||
TFC(EphemeronKeyBarrier, EphemeronKeyBarrier) \
|
||||
TFC(RecordWriteEmitRememberedSetSaveFP, WriteBarrier) \
|
||||
TFC(RecordWriteOmitRememberedSetSaveFP, WriteBarrier) \
|
||||
TFC(RecordWriteEmitRememberedSetIgnoreFP, WriteBarrier) \
|
||||
TFC(RecordWriteOmitRememberedSetIgnoreFP, WriteBarrier) \
|
||||
TFC(EphemeronKeyBarrierSaveFP, WriteBarrier) \
|
||||
TFC(EphemeronKeyBarrierIgnoreFP, WriteBarrier) \
|
||||
\
|
||||
/* Adaptor for CPP builtin */ \
|
||||
TFC(AdaptorWithBuiltinExitFrame, CppBuiltinAdaptor) \
|
||||
|
@ -113,9 +113,9 @@ TF_BUILTIN(DebugBreakTrampoline, CodeStubAssembler) {
|
||||
TailCallJSCode(code, context, function, new_target, arg_count);
|
||||
}
|
||||
|
||||
class RecordWriteCodeStubAssembler : public CodeStubAssembler {
|
||||
class WriteBarrierCodeStubAssembler : public CodeStubAssembler {
|
||||
public:
|
||||
explicit RecordWriteCodeStubAssembler(compiler::CodeAssemblerState* state)
|
||||
explicit WriteBarrierCodeStubAssembler(compiler::CodeAssemblerState* state)
|
||||
: CodeStubAssembler(state) {}
|
||||
|
||||
TNode<BoolT> IsMarking() {
|
||||
@ -172,80 +172,9 @@ class RecordWriteCodeStubAssembler : public CodeStubAssembler {
|
||||
}
|
||||
}
|
||||
|
||||
TNode<BoolT> ShouldSkipFPRegs(TNode<Smi> mode) {
|
||||
return TaggedEqual(mode, SmiConstant(SaveFPRegsMode::kIgnore));
|
||||
}
|
||||
|
||||
TNode<BoolT> ShouldEmitRememberSet(TNode<Smi> remembered_set) {
|
||||
return TaggedEqual(remembered_set, SmiConstant(RememberedSetAction::kEmit));
|
||||
}
|
||||
|
||||
template <typename Ret, typename Arg0, typename Arg1>
|
||||
void CallCFunction2WithCallerSavedRegistersMode(
|
||||
TNode<ExternalReference> function, TNode<Arg0> arg0, TNode<Arg1> arg1,
|
||||
TNode<Smi> mode, Label* next) {
|
||||
Label dont_save_fp(this), save_fp(this);
|
||||
Branch(ShouldSkipFPRegs(mode), &dont_save_fp, &save_fp);
|
||||
BIND(&dont_save_fp);
|
||||
{
|
||||
CallCFunctionWithCallerSavedRegisters(
|
||||
function, MachineTypeOf<Ret>::value, SaveFPRegsMode::kIgnore,
|
||||
std::make_pair(MachineTypeOf<Arg0>::value, arg0),
|
||||
std::make_pair(MachineTypeOf<Arg1>::value, arg1));
|
||||
Goto(next);
|
||||
}
|
||||
|
||||
BIND(&save_fp);
|
||||
{
|
||||
CallCFunctionWithCallerSavedRegisters(
|
||||
function, MachineTypeOf<Ret>::value, SaveFPRegsMode::kSave,
|
||||
std::make_pair(MachineTypeOf<Arg0>::value, arg0),
|
||||
std::make_pair(MachineTypeOf<Arg1>::value, arg1));
|
||||
Goto(next);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Ret, typename Arg0, typename Arg1, typename Arg2>
|
||||
void CallCFunction3WithCallerSavedRegistersMode(
|
||||
TNode<ExternalReference> function, TNode<Arg0> arg0, TNode<Arg1> arg1,
|
||||
TNode<Arg2> arg2, TNode<Smi> mode, Label* next) {
|
||||
Label dont_save_fp(this), save_fp(this);
|
||||
Branch(ShouldSkipFPRegs(mode), &dont_save_fp, &save_fp);
|
||||
BIND(&dont_save_fp);
|
||||
{
|
||||
CallCFunctionWithCallerSavedRegisters(
|
||||
function, MachineTypeOf<Ret>::value, SaveFPRegsMode::kIgnore,
|
||||
std::make_pair(MachineTypeOf<Arg0>::value, arg0),
|
||||
std::make_pair(MachineTypeOf<Arg1>::value, arg1),
|
||||
std::make_pair(MachineTypeOf<Arg2>::value, arg2));
|
||||
Goto(next);
|
||||
}
|
||||
|
||||
BIND(&save_fp);
|
||||
{
|
||||
CallCFunctionWithCallerSavedRegisters(
|
||||
function, MachineTypeOf<Ret>::value, SaveFPRegsMode::kSave,
|
||||
std::make_pair(MachineTypeOf<Arg0>::value, arg0),
|
||||
std::make_pair(MachineTypeOf<Arg1>::value, arg1),
|
||||
std::make_pair(MachineTypeOf<Arg2>::value, arg2));
|
||||
Goto(next);
|
||||
}
|
||||
}
|
||||
|
||||
void InsertIntoRememberedSetAndGotoSlow(TNode<IntPtrT> object,
|
||||
TNode<IntPtrT> slot, TNode<Smi> mode,
|
||||
Label* next) {
|
||||
TNode<IntPtrT> page = PageFromAddress(object);
|
||||
TNode<ExternalReference> function =
|
||||
ExternalConstant(ExternalReference::insert_remembered_set_function());
|
||||
CallCFunction2WithCallerSavedRegistersMode<Int32T, IntPtrT, IntPtrT>(
|
||||
function, page, slot, mode, next);
|
||||
}
|
||||
|
||||
void InsertIntoRememberedSetAndGoto(TNode<IntPtrT> object,
|
||||
TNode<IntPtrT> slot, TNode<Smi> mode,
|
||||
Label* next) {
|
||||
Label slow_path(this);
|
||||
void InsertIntoRememberedSet(TNode<IntPtrT> object, TNode<IntPtrT> slot,
|
||||
SaveFPRegsMode fp_mode) {
|
||||
Label slow_path(this), next(this);
|
||||
TNode<IntPtrT> page = PageFromAddress(object);
|
||||
|
||||
// Load address of SlotSet
|
||||
@ -257,11 +186,20 @@ class RecordWriteCodeStubAssembler : public CodeStubAssembler {
|
||||
|
||||
// Update cell
|
||||
SetBitInCell(bucket, slot_offset);
|
||||
|
||||
Goto(next);
|
||||
Goto(&next);
|
||||
|
||||
BIND(&slow_path);
|
||||
InsertIntoRememberedSetAndGotoSlow(object, slot, mode, next);
|
||||
{
|
||||
TNode<ExternalReference> function =
|
||||
ExternalConstant(ExternalReference::insert_remembered_set_function());
|
||||
CallCFunctionWithCallerSavedRegisters(
|
||||
function, MachineTypeOf<Int32T>::value, fp_mode,
|
||||
std::make_pair(MachineTypeOf<IntPtrT>::value, page),
|
||||
std::make_pair(MachineTypeOf<IntPtrT>::value, slot));
|
||||
Goto(&next);
|
||||
}
|
||||
|
||||
BIND(&next);
|
||||
}
|
||||
|
||||
TNode<IntPtrT> LoadSlotSet(TNode<IntPtrT> page, Label* slow_path) {
|
||||
@ -269,7 +207,6 @@ class RecordWriteCodeStubAssembler : public CodeStubAssembler {
|
||||
Load(MachineType::Pointer(), page,
|
||||
IntPtrConstant(MemoryChunk::kOldToNewSlotSetOffset)));
|
||||
GotoIf(WordEqual(slot_set, IntPtrConstant(0)), slow_path);
|
||||
|
||||
return slot_set;
|
||||
}
|
||||
|
||||
@ -306,32 +243,19 @@ class RecordWriteCodeStubAssembler : public CodeStubAssembler {
|
||||
StoreNoWriteBarrier(MachineRepresentation::kWord32, cell_address,
|
||||
TruncateIntPtrToInt32(new_cell_value));
|
||||
}
|
||||
};
|
||||
|
||||
TF_BUILTIN(RecordWrite, RecordWriteCodeStubAssembler) {
|
||||
Label generational_wb(this);
|
||||
Label incremental_wb(this);
|
||||
Label exit(this);
|
||||
|
||||
// In this method we limit the allocatable registers so we have to use
|
||||
// UncheckedParameter. Parameter does not work because the checked cast needs
|
||||
// more registers.
|
||||
auto remembered_set = UncheckedParameter<Smi>(Descriptor::kRememberedSet);
|
||||
Branch(ShouldEmitRememberSet(remembered_set), &generational_wb,
|
||||
&incremental_wb);
|
||||
|
||||
BIND(&generational_wb);
|
||||
{
|
||||
Label test_old_to_young_flags(this);
|
||||
Label store_buffer_exit(this), store_buffer_incremental_wb(this);
|
||||
void GenerationalWriteBarrier(SaveFPRegsMode fp_mode) {
|
||||
Label incremental_wb(this), test_old_to_young_flags(this),
|
||||
store_buffer_exit(this), store_buffer_incremental_wb(this), next(this);
|
||||
|
||||
// When incremental marking is not on, we skip cross generation pointer
|
||||
// checking here, because there are checks for
|
||||
// `kPointersFromHereAreInterestingMask` and
|
||||
// `kPointersToHereAreInterestingMask` in
|
||||
// `src/compiler/<arch>/code-generator-<arch>.cc` before calling this stub,
|
||||
// which serves as the cross generation checking.
|
||||
auto slot = UncheckedParameter<IntPtrT>(Descriptor::kSlot);
|
||||
// `src/compiler/<arch>/code-generator-<arch>.cc` before calling this
|
||||
// stub, which serves as the cross generation checking.
|
||||
auto slot =
|
||||
UncheckedParameter<IntPtrT>(WriteBarrierDescriptor::kSlotAddress);
|
||||
Branch(IsMarking(), &test_old_to_young_flags, &store_buffer_exit);
|
||||
|
||||
BIND(&test_old_to_young_flags);
|
||||
@ -339,14 +263,14 @@ TF_BUILTIN(RecordWrite, RecordWriteCodeStubAssembler) {
|
||||
// TODO(ishell): do a new-space range check instead.
|
||||
TNode<IntPtrT> value = BitcastTaggedToWord(Load<HeapObject>(slot));
|
||||
|
||||
// TODO(albertnetymk): Try to cache the page flag for value and object,
|
||||
// instead of calling IsPageFlagSet each time.
|
||||
// TODO(albertnetymk): Try to cache the page flag for value and
|
||||
// object, instead of calling IsPageFlagSet each time.
|
||||
TNode<BoolT> value_is_young =
|
||||
IsPageFlagSet(value, MemoryChunk::kIsInYoungGenerationMask);
|
||||
GotoIfNot(value_is_young, &incremental_wb);
|
||||
|
||||
TNode<IntPtrT> object =
|
||||
BitcastTaggedToWord(UncheckedParameter<Object>(Descriptor::kObject));
|
||||
TNode<IntPtrT> object = BitcastTaggedToWord(
|
||||
UncheckedParameter<Object>(WriteBarrierDescriptor::kObject));
|
||||
TNode<BoolT> object_is_young =
|
||||
IsPageFlagSet(object, MemoryChunk::kIsInYoungGenerationMask);
|
||||
Branch(object_is_young, &incremental_wb, &store_buffer_incremental_wb);
|
||||
@ -354,27 +278,40 @@ TF_BUILTIN(RecordWrite, RecordWriteCodeStubAssembler) {
|
||||
|
||||
BIND(&store_buffer_exit);
|
||||
{
|
||||
auto fp_mode = UncheckedParameter<Smi>(Descriptor::kFPMode);
|
||||
TNode<IntPtrT> object =
|
||||
BitcastTaggedToWord(UncheckedParameter<Object>(Descriptor::kObject));
|
||||
InsertIntoRememberedSetAndGoto(object, slot, fp_mode, &exit);
|
||||
TNode<IntPtrT> object = BitcastTaggedToWord(
|
||||
UncheckedParameter<Object>(WriteBarrierDescriptor::kObject));
|
||||
InsertIntoRememberedSet(object, slot, fp_mode);
|
||||
Goto(&next);
|
||||
}
|
||||
|
||||
BIND(&store_buffer_incremental_wb);
|
||||
{
|
||||
auto fp_mode = UncheckedParameter<Smi>(Descriptor::kFPMode);
|
||||
TNode<IntPtrT> object =
|
||||
BitcastTaggedToWord(UncheckedParameter<Object>(Descriptor::kObject));
|
||||
InsertIntoRememberedSetAndGoto(object, slot, fp_mode, &incremental_wb);
|
||||
TNode<IntPtrT> object = BitcastTaggedToWord(
|
||||
UncheckedParameter<Object>(WriteBarrierDescriptor::kObject));
|
||||
InsertIntoRememberedSet(object, slot, fp_mode);
|
||||
Goto(&incremental_wb);
|
||||
}
|
||||
|
||||
BIND(&incremental_wb);
|
||||
{
|
||||
TNode<IntPtrT> value = BitcastTaggedToWord(Load<HeapObject>(slot));
|
||||
IncrementalWriteBarrier(slot, value, fp_mode);
|
||||
Goto(&next);
|
||||
}
|
||||
|
||||
BIND(&next);
|
||||
}
|
||||
|
||||
BIND(&incremental_wb);
|
||||
{
|
||||
Label call_incremental_wb(this);
|
||||
|
||||
auto slot = UncheckedParameter<IntPtrT>(Descriptor::kSlot);
|
||||
void IncrementalWriteBarrier(SaveFPRegsMode fp_mode) {
|
||||
auto slot =
|
||||
UncheckedParameter<IntPtrT>(WriteBarrierDescriptor::kSlotAddress);
|
||||
TNode<IntPtrT> value = BitcastTaggedToWord(Load<HeapObject>(slot));
|
||||
IncrementalWriteBarrier(slot, value, fp_mode);
|
||||
}
|
||||
|
||||
void IncrementalWriteBarrier(TNode<IntPtrT> slot, TNode<IntPtrT> value,
|
||||
SaveFPRegsMode fp_mode) {
|
||||
Label call_incremental_wb(this), next(this);
|
||||
|
||||
// There are two cases we need to call incremental write barrier.
|
||||
// 1) value_is_white
|
||||
@ -383,52 +320,92 @@ TF_BUILTIN(RecordWrite, RecordWriteCodeStubAssembler) {
|
||||
// 2) is_compacting && value_in_EC && obj_isnt_skip
|
||||
// is_compacting = true when is_marking = true
|
||||
GotoIfNot(IsPageFlagSet(value, MemoryChunk::kEvacuationCandidateMask),
|
||||
&exit);
|
||||
&next);
|
||||
|
||||
TNode<IntPtrT> object =
|
||||
BitcastTaggedToWord(UncheckedParameter<Object>(Descriptor::kObject));
|
||||
TNode<IntPtrT> object = BitcastTaggedToWord(
|
||||
UncheckedParameter<Object>(WriteBarrierDescriptor::kObject));
|
||||
Branch(
|
||||
IsPageFlagSet(object, MemoryChunk::kSkipEvacuationSlotsRecordingMask),
|
||||
&exit, &call_incremental_wb);
|
||||
&next, &call_incremental_wb);
|
||||
|
||||
BIND(&call_incremental_wb);
|
||||
{
|
||||
TNode<ExternalReference> function = ExternalConstant(
|
||||
ExternalReference::write_barrier_marking_from_code_function());
|
||||
auto fp_mode = UncheckedParameter<Smi>(Descriptor::kFPMode);
|
||||
TNode<IntPtrT> object =
|
||||
BitcastTaggedToWord(UncheckedParameter<Object>(Descriptor::kObject));
|
||||
CallCFunction2WithCallerSavedRegistersMode<Int32T, IntPtrT, IntPtrT>(
|
||||
function, object, slot, fp_mode, &exit);
|
||||
TNode<IntPtrT> object = BitcastTaggedToWord(
|
||||
UncheckedParameter<Object>(WriteBarrierDescriptor::kObject));
|
||||
CallCFunctionWithCallerSavedRegisters(
|
||||
function, MachineTypeOf<Int32T>::value, fp_mode,
|
||||
std::make_pair(MachineTypeOf<IntPtrT>::value, object),
|
||||
std::make_pair(MachineTypeOf<IntPtrT>::value, slot));
|
||||
Goto(&next);
|
||||
}
|
||||
BIND(&next);
|
||||
}
|
||||
|
||||
BIND(&exit);
|
||||
IncrementCounter(isolate()->counters()->write_barriers(), 1);
|
||||
Return(TrueConstant());
|
||||
void GenerateRecordWrite(RememberedSetAction rs_mode,
|
||||
SaveFPRegsMode fp_mode) {
|
||||
switch (rs_mode) {
|
||||
case RememberedSetAction::kEmit:
|
||||
GenerationalWriteBarrier(fp_mode);
|
||||
break;
|
||||
case RememberedSetAction::kOmit:
|
||||
IncrementalWriteBarrier(fp_mode);
|
||||
break;
|
||||
}
|
||||
IncrementCounter(isolate()->counters()->write_barriers(), 1);
|
||||
Return(TrueConstant());
|
||||
}
|
||||
|
||||
void GenerateEphemeronKeyBarrier(SaveFPRegsMode fp_mode) {
|
||||
TNode<ExternalReference> function = ExternalConstant(
|
||||
ExternalReference::ephemeron_key_write_barrier_function());
|
||||
TNode<ExternalReference> isolate_constant =
|
||||
ExternalConstant(ExternalReference::isolate_address(isolate()));
|
||||
// In this method we limit the allocatable registers so we have to use
|
||||
// UncheckedParameter. Parameter does not work because the checked cast
|
||||
// needs more registers.
|
||||
auto address =
|
||||
UncheckedParameter<IntPtrT>(WriteBarrierDescriptor::kSlotAddress);
|
||||
TNode<IntPtrT> object = BitcastTaggedToWord(
|
||||
UncheckedParameter<Object>(WriteBarrierDescriptor::kObject));
|
||||
|
||||
CallCFunctionWithCallerSavedRegisters(
|
||||
function, MachineTypeOf<Int32T>::value, fp_mode,
|
||||
std::make_pair(MachineTypeOf<IntPtrT>::value, object),
|
||||
std::make_pair(MachineTypeOf<IntPtrT>::value, address),
|
||||
std::make_pair(MachineTypeOf<ExternalReference>::value,
|
||||
isolate_constant));
|
||||
|
||||
IncrementCounter(isolate()->counters()->write_barriers(), 1);
|
||||
Return(TrueConstant());
|
||||
}
|
||||
};
|
||||
|
||||
TF_BUILTIN(RecordWriteEmitRememberedSetSaveFP, WriteBarrierCodeStubAssembler) {
|
||||
GenerateRecordWrite(RememberedSetAction::kEmit, SaveFPRegsMode::kSave);
|
||||
}
|
||||
|
||||
TF_BUILTIN(EphemeronKeyBarrier, RecordWriteCodeStubAssembler) {
|
||||
Label exit(this);
|
||||
TF_BUILTIN(RecordWriteOmitRememberedSetSaveFP, WriteBarrierCodeStubAssembler) {
|
||||
GenerateRecordWrite(RememberedSetAction::kOmit, SaveFPRegsMode::kSave);
|
||||
}
|
||||
|
||||
TNode<ExternalReference> function = ExternalConstant(
|
||||
ExternalReference::ephemeron_key_write_barrier_function());
|
||||
TNode<ExternalReference> isolate_constant =
|
||||
ExternalConstant(ExternalReference::isolate_address(isolate()));
|
||||
// In this method we limit the allocatable registers so we have to use
|
||||
// UncheckedParameter. Parameter does not work because the checked cast needs
|
||||
// more registers.
|
||||
auto address = UncheckedParameter<IntPtrT>(Descriptor::kSlotAddress);
|
||||
TNode<IntPtrT> object =
|
||||
BitcastTaggedToWord(UncheckedParameter<Object>(Descriptor::kObject));
|
||||
TNode<Smi> fp_mode = UncheckedParameter<Smi>(Descriptor::kFPMode);
|
||||
CallCFunction3WithCallerSavedRegistersMode<Int32T, IntPtrT, IntPtrT,
|
||||
ExternalReference>(
|
||||
function, object, address, isolate_constant, fp_mode, &exit);
|
||||
TF_BUILTIN(RecordWriteEmitRememberedSetIgnoreFP,
|
||||
WriteBarrierCodeStubAssembler) {
|
||||
GenerateRecordWrite(RememberedSetAction::kEmit, SaveFPRegsMode::kIgnore);
|
||||
}
|
||||
|
||||
BIND(&exit);
|
||||
IncrementCounter(isolate()->counters()->write_barriers(), 1);
|
||||
Return(TrueConstant());
|
||||
TF_BUILTIN(RecordWriteOmitRememberedSetIgnoreFP,
|
||||
WriteBarrierCodeStubAssembler) {
|
||||
GenerateRecordWrite(RememberedSetAction::kOmit, SaveFPRegsMode::kIgnore);
|
||||
}
|
||||
|
||||
TF_BUILTIN(EphemeronKeyBarrierSaveFP, WriteBarrierCodeStubAssembler) {
|
||||
GenerateEphemeronKeyBarrier(SaveFPRegsMode::kSave);
|
||||
}
|
||||
|
||||
TF_BUILTIN(EphemeronKeyBarrierIgnoreFP, WriteBarrierCodeStubAssembler) {
|
||||
GenerateEphemeronKeyBarrier(SaveFPRegsMode::kIgnore);
|
||||
}
|
||||
|
||||
class DeletePropertyBaseAssembler : public AccessorAssembler {
|
||||
|
@ -83,6 +83,37 @@ class Builtins {
|
||||
static BytecodeOffset GetContinuationBytecodeOffset(Name name);
|
||||
static Name GetBuiltinFromBytecodeOffset(BytecodeOffset);
|
||||
|
||||
static Name GetRecordWriteStub(RememberedSetAction remembered_set_action,
|
||||
SaveFPRegsMode fp_mode) {
|
||||
switch (remembered_set_action) {
|
||||
case RememberedSetAction::kEmit:
|
||||
switch (fp_mode) {
|
||||
case SaveFPRegsMode::kIgnore:
|
||||
return Builtins::kRecordWriteEmitRememberedSetIgnoreFP;
|
||||
case SaveFPRegsMode::kSave:
|
||||
return Builtins::kRecordWriteEmitRememberedSetSaveFP;
|
||||
}
|
||||
case RememberedSetAction::kOmit:
|
||||
switch (fp_mode) {
|
||||
case SaveFPRegsMode::kIgnore:
|
||||
return Builtins::kRecordWriteOmitRememberedSetIgnoreFP;
|
||||
case SaveFPRegsMode::kSave:
|
||||
return Builtins::kRecordWriteOmitRememberedSetSaveFP;
|
||||
}
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
static constexpr Name GetEphemeronKeyBarrierStub(SaveFPRegsMode fp_mode) {
|
||||
switch (fp_mode) {
|
||||
case SaveFPRegsMode::kIgnore:
|
||||
return Builtins::kEphemeronKeyBarrierIgnoreFP;
|
||||
case SaveFPRegsMode::kSave:
|
||||
return Builtins::kEphemeronKeyBarrierSaveFP;
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
// Convenience wrappers.
|
||||
Handle<Code> CallFunction(ConvertReceiverMode = ConvertReceiverMode::kAny);
|
||||
Handle<Code> Call(ConvertReceiverMode = ConvertReceiverMode::kAny);
|
||||
|
@ -20,7 +20,7 @@ constexpr auto CallInterfaceDescriptor::DefaultRegisterArray() {
|
||||
}
|
||||
|
||||
// static
|
||||
constexpr auto RecordWriteDescriptor::registers() {
|
||||
constexpr auto WriteBarrierDescriptor::registers() {
|
||||
return RegisterArray(r0, r1, r2, r3, r4, kReturnRegister0);
|
||||
}
|
||||
|
||||
@ -29,11 +29,6 @@ constexpr auto DynamicCheckMapsDescriptor::registers() {
|
||||
return RegisterArray(r0, r1, r2, r3, cp);
|
||||
}
|
||||
|
||||
// static
|
||||
constexpr auto EphemeronKeyBarrierDescriptor::registers() {
|
||||
return RegisterArray(r0, r1, r2, r3, r4, kReturnRegister0);
|
||||
}
|
||||
|
||||
// static
|
||||
constexpr Register LoadDescriptor::ReceiverRegister() { return r1; }
|
||||
// static
|
||||
|
@ -711,75 +711,51 @@ void TurboAssembler::RestoreRegisters(RegList registers) {
|
||||
|
||||
void TurboAssembler::CallEphemeronKeyBarrier(Register object, Operand offset,
|
||||
SaveFPRegsMode fp_mode) {
|
||||
EphemeronKeyBarrierDescriptor descriptor;
|
||||
WriteBarrierDescriptor descriptor;
|
||||
RegList registers = descriptor.allocatable_registers();
|
||||
|
||||
SaveRegisters(registers);
|
||||
|
||||
Register object_parameter(
|
||||
descriptor.GetRegisterParameter(EphemeronKeyBarrierDescriptor::kObject));
|
||||
Register slot_parameter(descriptor.GetRegisterParameter(
|
||||
EphemeronKeyBarrierDescriptor::kSlotAddress));
|
||||
Register fp_mode_parameter(
|
||||
descriptor.GetRegisterParameter(EphemeronKeyBarrierDescriptor::kFPMode));
|
||||
descriptor.GetRegisterParameter(WriteBarrierDescriptor::kObject));
|
||||
Register slot_parameter(
|
||||
descriptor.GetRegisterParameter(WriteBarrierDescriptor::kSlotAddress));
|
||||
|
||||
MoveObjectAndSlot(object_parameter, slot_parameter, object, offset);
|
||||
Move(fp_mode_parameter, Smi::FromEnum(fp_mode));
|
||||
Call(isolate()->builtins()->builtin_handle(Builtins::kEphemeronKeyBarrier),
|
||||
Call(isolate()->builtins()->builtin_handle(
|
||||
Builtins::GetEphemeronKeyBarrierStub(fp_mode)),
|
||||
RelocInfo::CODE_TARGET);
|
||||
RestoreRegisters(registers);
|
||||
}
|
||||
|
||||
void TurboAssembler::CallRecordWriteStub(
|
||||
Register object, Operand offset, RememberedSetAction remembered_set_action,
|
||||
SaveFPRegsMode fp_mode) {
|
||||
CallRecordWriteStub(object, offset, remembered_set_action, fp_mode,
|
||||
Builtins::kRecordWrite, kNullAddress);
|
||||
}
|
||||
|
||||
void TurboAssembler::CallRecordWriteStub(
|
||||
Register object, Operand offset, RememberedSetAction remembered_set_action,
|
||||
SaveFPRegsMode fp_mode, Address wasm_target) {
|
||||
CallRecordWriteStub(object, offset, remembered_set_action, fp_mode,
|
||||
Builtins::kNoBuiltinId, wasm_target);
|
||||
}
|
||||
|
||||
void TurboAssembler::CallRecordWriteStub(
|
||||
Register object, Operand offset, RememberedSetAction remembered_set_action,
|
||||
SaveFPRegsMode fp_mode, int builtin_index, Address wasm_target) {
|
||||
DCHECK_NE(builtin_index == Builtins::kNoBuiltinId,
|
||||
wasm_target == kNullAddress);
|
||||
// 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.
|
||||
|
||||
RecordWriteDescriptor descriptor;
|
||||
SaveFPRegsMode fp_mode, StubCallMode mode) {
|
||||
WriteBarrierDescriptor descriptor;
|
||||
RegList registers = descriptor.allocatable_registers();
|
||||
|
||||
SaveRegisters(registers);
|
||||
|
||||
Register object_parameter(
|
||||
descriptor.GetRegisterParameter(RecordWriteDescriptor::kObject));
|
||||
descriptor.GetRegisterParameter(WriteBarrierDescriptor::kObject));
|
||||
Register slot_parameter(
|
||||
descriptor.GetRegisterParameter(RecordWriteDescriptor::kSlot));
|
||||
Register remembered_set_parameter(
|
||||
descriptor.GetRegisterParameter(RecordWriteDescriptor::kRememberedSet));
|
||||
Register fp_mode_parameter(
|
||||
descriptor.GetRegisterParameter(RecordWriteDescriptor::kFPMode));
|
||||
descriptor.GetRegisterParameter(WriteBarrierDescriptor::kSlotAddress));
|
||||
|
||||
MoveObjectAndSlot(object_parameter, slot_parameter, object, offset);
|
||||
|
||||
Move(remembered_set_parameter, Smi::FromEnum(remembered_set_action));
|
||||
Move(fp_mode_parameter, Smi::FromEnum(fp_mode));
|
||||
if (builtin_index == Builtins::kNoBuiltinId) {
|
||||
if (mode == StubCallMode::kCallWasmRuntimeStub) {
|
||||
auto wasm_target =
|
||||
wasm::WasmCode::GetRecordWriteStub(remembered_set_action, fp_mode);
|
||||
Call(wasm_target, RelocInfo::WASM_STUB_CALL);
|
||||
} else if (options().inline_offheap_trampolines) {
|
||||
CallBuiltin(builtin_index);
|
||||
} else {
|
||||
Handle<Code> code_target =
|
||||
isolate()->builtins()->builtin_handle(Builtins::kRecordWrite);
|
||||
Call(code_target, RelocInfo::CODE_TARGET);
|
||||
auto builtin_index =
|
||||
Builtins::GetRecordWriteStub(remembered_set_action, fp_mode);
|
||||
if (options().inline_offheap_trampolines) {
|
||||
CallBuiltin(builtin_index);
|
||||
} else {
|
||||
Handle<Code> code_target =
|
||||
isolate()->builtins()->builtin_handle(builtin_index);
|
||||
Call(code_target, RelocInfo::CODE_TARGET);
|
||||
}
|
||||
}
|
||||
|
||||
RestoreRegisters(registers);
|
||||
|
@ -377,15 +377,14 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
|
||||
void SaveRegisters(RegList registers);
|
||||
void RestoreRegisters(RegList registers);
|
||||
|
||||
void CallRecordWriteStub(Register object, Operand offset,
|
||||
RememberedSetAction remembered_set_action,
|
||||
SaveFPRegsMode fp_mode);
|
||||
void CallRecordWriteStub(Register object, Operand offset,
|
||||
RememberedSetAction remembered_set_action,
|
||||
SaveFPRegsMode fp_mode, Address wasm_target);
|
||||
void CallEphemeronKeyBarrier(Register object, Operand offset,
|
||||
SaveFPRegsMode fp_mode);
|
||||
|
||||
void CallRecordWriteStub(
|
||||
Register object, Operand offset,
|
||||
RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode,
|
||||
StubCallMode mode = StubCallMode::kCallBuiltinPointer);
|
||||
|
||||
// For a given |object| and |offset|:
|
||||
// - Move |object| to |dst_object|.
|
||||
// - Compute the address of the slot pointed to by |offset| in |object| and
|
||||
@ -622,11 +621,6 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
|
||||
|
||||
void CallCFunctionHelper(Register function, int num_reg_arguments,
|
||||
int num_double_arguments);
|
||||
|
||||
void CallRecordWriteStub(Register object, Operand offset,
|
||||
RememberedSetAction remembered_set_action,
|
||||
SaveFPRegsMode fp_mode, int builtin_index,
|
||||
Address wasm_target);
|
||||
};
|
||||
|
||||
// MacroAssembler implements a collection of frequently used macros.
|
||||
|
@ -21,7 +21,7 @@ constexpr auto CallInterfaceDescriptor::DefaultRegisterArray() {
|
||||
}
|
||||
|
||||
// static
|
||||
constexpr auto RecordWriteDescriptor::registers() {
|
||||
constexpr auto WriteBarrierDescriptor::registers() {
|
||||
return RegisterArray(x0, x1, x2, x3, x4, kReturnRegister0);
|
||||
}
|
||||
|
||||
@ -30,11 +30,6 @@ constexpr auto DynamicCheckMapsDescriptor::registers() {
|
||||
return RegisterArray(x0, x1, x2, x3, cp);
|
||||
}
|
||||
|
||||
// static
|
||||
constexpr auto EphemeronKeyBarrierDescriptor::registers() {
|
||||
return RegisterArray(x0, x1, x2, x3, x4, kReturnRegister0);
|
||||
}
|
||||
|
||||
// static
|
||||
constexpr Register LoadDescriptor::ReceiverRegister() { return x1; }
|
||||
// static
|
||||
|
@ -2943,76 +2943,52 @@ void TurboAssembler::RestoreRegisters(RegList registers) {
|
||||
|
||||
void TurboAssembler::CallEphemeronKeyBarrier(Register object, Operand offset,
|
||||
SaveFPRegsMode fp_mode) {
|
||||
EphemeronKeyBarrierDescriptor descriptor;
|
||||
WriteBarrierDescriptor descriptor;
|
||||
RegList registers = descriptor.allocatable_registers();
|
||||
|
||||
SaveRegisters(registers);
|
||||
|
||||
Register object_parameter(
|
||||
descriptor.GetRegisterParameter(EphemeronKeyBarrierDescriptor::kObject));
|
||||
Register slot_parameter(descriptor.GetRegisterParameter(
|
||||
EphemeronKeyBarrierDescriptor::kSlotAddress));
|
||||
Register fp_mode_parameter(
|
||||
descriptor.GetRegisterParameter(EphemeronKeyBarrierDescriptor::kFPMode));
|
||||
descriptor.GetRegisterParameter(WriteBarrierDescriptor::kObject));
|
||||
Register slot_parameter(
|
||||
descriptor.GetRegisterParameter(WriteBarrierDescriptor::kSlotAddress));
|
||||
|
||||
MoveObjectAndSlot(object_parameter, slot_parameter, object, offset);
|
||||
|
||||
Mov(fp_mode_parameter, Smi::FromEnum(fp_mode));
|
||||
Call(isolate()->builtins()->builtin_handle(Builtins::kEphemeronKeyBarrier),
|
||||
Call(isolate()->builtins()->builtin_handle(
|
||||
Builtins::GetEphemeronKeyBarrierStub(fp_mode)),
|
||||
RelocInfo::CODE_TARGET);
|
||||
RestoreRegisters(registers);
|
||||
}
|
||||
|
||||
void TurboAssembler::CallRecordWriteStub(
|
||||
Register object, Operand offset, RememberedSetAction remembered_set_action,
|
||||
SaveFPRegsMode fp_mode) {
|
||||
CallRecordWriteStub(object, offset, remembered_set_action, fp_mode,
|
||||
Builtins::kRecordWrite, kNullAddress);
|
||||
}
|
||||
|
||||
void TurboAssembler::CallRecordWriteStub(
|
||||
Register object, Operand offset, RememberedSetAction remembered_set_action,
|
||||
SaveFPRegsMode fp_mode, Address wasm_target) {
|
||||
CallRecordWriteStub(object, offset, remembered_set_action, fp_mode,
|
||||
Builtins::kNoBuiltinId, wasm_target);
|
||||
}
|
||||
|
||||
void TurboAssembler::CallRecordWriteStub(
|
||||
Register object, Operand offset, RememberedSetAction remembered_set_action,
|
||||
SaveFPRegsMode fp_mode, int builtin_index, Address wasm_target) {
|
||||
DCHECK_NE(builtin_index == Builtins::kNoBuiltinId,
|
||||
wasm_target == kNullAddress);
|
||||
// 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.
|
||||
|
||||
RecordWriteDescriptor descriptor;
|
||||
SaveFPRegsMode fp_mode, StubCallMode mode) {
|
||||
WriteBarrierDescriptor descriptor;
|
||||
RegList registers = descriptor.allocatable_registers();
|
||||
|
||||
SaveRegisters(registers);
|
||||
|
||||
Register object_parameter(
|
||||
descriptor.GetRegisterParameter(RecordWriteDescriptor::kObject));
|
||||
descriptor.GetRegisterParameter(WriteBarrierDescriptor::kObject));
|
||||
Register slot_parameter(
|
||||
descriptor.GetRegisterParameter(RecordWriteDescriptor::kSlot));
|
||||
Register remembered_set_parameter(
|
||||
descriptor.GetRegisterParameter(RecordWriteDescriptor::kRememberedSet));
|
||||
Register fp_mode_parameter(
|
||||
descriptor.GetRegisterParameter(RecordWriteDescriptor::kFPMode));
|
||||
descriptor.GetRegisterParameter(WriteBarrierDescriptor::kSlotAddress));
|
||||
|
||||
MoveObjectAndSlot(object_parameter, slot_parameter, object, offset);
|
||||
|
||||
Mov(remembered_set_parameter, Smi::FromEnum(remembered_set_action));
|
||||
Mov(fp_mode_parameter, Smi::FromEnum(fp_mode));
|
||||
if (builtin_index == Builtins::kNoBuiltinId) {
|
||||
if (mode == StubCallMode::kCallWasmRuntimeStub) {
|
||||
auto wasm_target =
|
||||
wasm::WasmCode::GetRecordWriteStub(remembered_set_action, fp_mode);
|
||||
Call(wasm_target, RelocInfo::WASM_STUB_CALL);
|
||||
} else if (options().inline_offheap_trampolines) {
|
||||
CallBuiltin(builtin_index);
|
||||
} else {
|
||||
Handle<Code> code_target =
|
||||
isolate()->builtins()->builtin_handle(Builtins::kRecordWrite);
|
||||
Call(code_target, RelocInfo::CODE_TARGET);
|
||||
auto builtin_index =
|
||||
Builtins::GetRecordWriteStub(remembered_set_action, fp_mode);
|
||||
if (options().inline_offheap_trampolines) {
|
||||
CallBuiltin(builtin_index);
|
||||
} else {
|
||||
Handle<Code> code_target =
|
||||
isolate()->builtins()->builtin_handle(builtin_index);
|
||||
Call(code_target, RelocInfo::CODE_TARGET);
|
||||
}
|
||||
}
|
||||
|
||||
RestoreRegisters(registers);
|
||||
|
@ -840,15 +840,14 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
|
||||
void SaveRegisters(RegList registers);
|
||||
void RestoreRegisters(RegList registers);
|
||||
|
||||
void CallRecordWriteStub(Register object, Operand offset,
|
||||
RememberedSetAction remembered_set_action,
|
||||
SaveFPRegsMode fp_mode);
|
||||
void CallRecordWriteStub(Register object, Operand offset,
|
||||
RememberedSetAction remembered_set_action,
|
||||
SaveFPRegsMode fp_mode, Address wasm_target);
|
||||
void CallEphemeronKeyBarrier(Register object, Operand offset,
|
||||
SaveFPRegsMode fp_mode);
|
||||
|
||||
void CallRecordWriteStub(
|
||||
Register object, Operand offset,
|
||||
RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode,
|
||||
StubCallMode mode = StubCallMode::kCallBuiltinPointer);
|
||||
|
||||
// For a given |object| and |offset|:
|
||||
// - Move |object| to |dst_object|.
|
||||
// - Compute the address of the slot pointed to by |offset| in |object| and
|
||||
@ -1462,11 +1461,6 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
|
||||
byte* pc);
|
||||
|
||||
void JumpHelper(int64_t offset, RelocInfo::Mode rmode, Condition cond = al);
|
||||
|
||||
void CallRecordWriteStub(Register object, Operand offset,
|
||||
RememberedSetAction remembered_set_action,
|
||||
SaveFPRegsMode fp_mode, int builtin_index,
|
||||
Address wasm_target);
|
||||
};
|
||||
|
||||
class V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler {
|
||||
|
@ -19,7 +19,7 @@ constexpr auto CallInterfaceDescriptor::DefaultRegisterArray() {
|
||||
}
|
||||
|
||||
// static
|
||||
constexpr auto RecordWriteDescriptor::registers() {
|
||||
constexpr auto WriteBarrierDescriptor::registers() {
|
||||
return RegisterArray(ecx, edx, esi, edi, kReturnRegister0);
|
||||
}
|
||||
|
||||
@ -28,11 +28,6 @@ constexpr auto DynamicCheckMapsDescriptor::registers() {
|
||||
return RegisterArray(eax, ecx, edx, edi, esi);
|
||||
}
|
||||
|
||||
// static
|
||||
constexpr auto EphemeronKeyBarrierDescriptor::registers() {
|
||||
return RegisterArray(ecx, edx, esi, edi, kReturnRegister0);
|
||||
}
|
||||
|
||||
// static
|
||||
constexpr Register LoadDescriptor::ReceiverRegister() { return edx; }
|
||||
// static
|
||||
|
@ -415,17 +415,15 @@ void TurboAssembler::RestoreRegisters(RegList registers) {
|
||||
|
||||
void TurboAssembler::CallEphemeronKeyBarrier(Register object, Register address,
|
||||
SaveFPRegsMode fp_mode) {
|
||||
EphemeronKeyBarrierDescriptor descriptor;
|
||||
WriteBarrierDescriptor descriptor;
|
||||
RegList registers = descriptor.allocatable_registers();
|
||||
|
||||
SaveRegisters(registers);
|
||||
|
||||
Register object_parameter(
|
||||
descriptor.GetRegisterParameter(EphemeronKeyBarrierDescriptor::kObject));
|
||||
Register slot_parameter(descriptor.GetRegisterParameter(
|
||||
EphemeronKeyBarrierDescriptor::kSlotAddress));
|
||||
Register fp_mode_parameter(
|
||||
descriptor.GetRegisterParameter(EphemeronKeyBarrierDescriptor::kFPMode));
|
||||
descriptor.GetRegisterParameter(WriteBarrierDescriptor::kObject));
|
||||
Register slot_parameter(
|
||||
descriptor.GetRegisterParameter(WriteBarrierDescriptor::kSlotAddress));
|
||||
|
||||
push(object);
|
||||
push(address);
|
||||
@ -433,52 +431,25 @@ void TurboAssembler::CallEphemeronKeyBarrier(Register object, Register address,
|
||||
pop(slot_parameter);
|
||||
pop(object_parameter);
|
||||
|
||||
Move(fp_mode_parameter, Smi::FromEnum(fp_mode));
|
||||
Call(isolate()->builtins()->builtin_handle(Builtins::kEphemeronKeyBarrier),
|
||||
Call(isolate()->builtins()->builtin_handle(
|
||||
Builtins::GetEphemeronKeyBarrierStub(fp_mode)),
|
||||
RelocInfo::CODE_TARGET);
|
||||
|
||||
RestoreRegisters(registers);
|
||||
}
|
||||
|
||||
void TurboAssembler::CallRecordWriteStub(
|
||||
Register object, Register address,
|
||||
RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode) {
|
||||
CallRecordWriteStub(object, address, remembered_set_action, fp_mode,
|
||||
Builtins::kRecordWrite, kNullAddress);
|
||||
}
|
||||
|
||||
void TurboAssembler::CallRecordWriteStub(
|
||||
Register object, Register address,
|
||||
RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode,
|
||||
Address wasm_target) {
|
||||
CallRecordWriteStub(object, address, remembered_set_action, fp_mode,
|
||||
Builtins::kNoBuiltinId, wasm_target);
|
||||
}
|
||||
|
||||
void TurboAssembler::CallRecordWriteStub(
|
||||
Register object, Register address,
|
||||
RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode,
|
||||
int builtin_index, Address wasm_target) {
|
||||
DCHECK_NE(builtin_index == Builtins::kNoBuiltinId,
|
||||
wasm_target == kNullAddress);
|
||||
// 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.
|
||||
|
||||
RecordWriteDescriptor descriptor;
|
||||
StubCallMode mode) {
|
||||
WriteBarrierDescriptor descriptor;
|
||||
RegList registers = descriptor.allocatable_registers();
|
||||
|
||||
SaveRegisters(registers);
|
||||
|
||||
Register object_parameter(
|
||||
descriptor.GetRegisterParameter(RecordWriteDescriptor::kObject));
|
||||
descriptor.GetRegisterParameter(WriteBarrierDescriptor::kObject));
|
||||
Register slot_parameter(
|
||||
descriptor.GetRegisterParameter(RecordWriteDescriptor::kSlot));
|
||||
Register remembered_set_parameter(
|
||||
descriptor.GetRegisterParameter(RecordWriteDescriptor::kRememberedSet));
|
||||
Register fp_mode_parameter(
|
||||
descriptor.GetRegisterParameter(RecordWriteDescriptor::kFPMode));
|
||||
descriptor.GetRegisterParameter(WriteBarrierDescriptor::kSlotAddress));
|
||||
|
||||
push(object);
|
||||
push(address);
|
||||
@ -486,17 +457,21 @@ void TurboAssembler::CallRecordWriteStub(
|
||||
pop(slot_parameter);
|
||||
pop(object_parameter);
|
||||
|
||||
Move(remembered_set_parameter, Smi::FromEnum(remembered_set_action));
|
||||
Move(fp_mode_parameter, Smi::FromEnum(fp_mode));
|
||||
if (builtin_index == Builtins::kNoBuiltinId) {
|
||||
if (mode == StubCallMode::kCallWasmRuntimeStub) {
|
||||
// Use {wasm_call} for direct Wasm call within a module.
|
||||
auto wasm_target =
|
||||
wasm::WasmCode::GetRecordWriteStub(remembered_set_action, fp_mode);
|
||||
wasm_call(wasm_target, RelocInfo::WASM_STUB_CALL);
|
||||
} else if (options().inline_offheap_trampolines) {
|
||||
CallBuiltin(builtin_index);
|
||||
} else {
|
||||
Handle<Code> code_target =
|
||||
isolate()->builtins()->builtin_handle(Builtins::kRecordWrite);
|
||||
Call(code_target, RelocInfo::CODE_TARGET);
|
||||
auto builtin_index =
|
||||
Builtins::GetRecordWriteStub(remembered_set_action, fp_mode);
|
||||
if (options().inline_offheap_trampolines) {
|
||||
CallBuiltin(builtin_index);
|
||||
} else {
|
||||
Handle<Code> code_target =
|
||||
isolate()->builtins()->builtin_handle(builtin_index);
|
||||
Call(code_target, RelocInfo::CODE_TARGET);
|
||||
}
|
||||
}
|
||||
|
||||
RestoreRegisters(registers);
|
||||
|
@ -440,15 +440,14 @@ class V8_EXPORT_PRIVATE TurboAssembler : public SharedTurboAssembler {
|
||||
void SaveRegisters(RegList registers);
|
||||
void RestoreRegisters(RegList registers);
|
||||
|
||||
void CallRecordWriteStub(Register object, Register address,
|
||||
RememberedSetAction remembered_set_action,
|
||||
SaveFPRegsMode fp_mode);
|
||||
void CallRecordWriteStub(Register object, Register address,
|
||||
RememberedSetAction remembered_set_action,
|
||||
SaveFPRegsMode fp_mode, Address wasm_target);
|
||||
void CallEphemeronKeyBarrier(Register object, Register address,
|
||||
SaveFPRegsMode fp_mode);
|
||||
|
||||
void CallRecordWriteStub(
|
||||
Register object, Register address,
|
||||
RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode,
|
||||
StubCallMode mode = StubCallMode::kCallBuiltinPointer);
|
||||
|
||||
// Calculate how much stack space (in bytes) are required to store caller
|
||||
// registers excluding those specified in the arguments.
|
||||
int RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode,
|
||||
@ -488,11 +487,6 @@ class V8_EXPORT_PRIVATE TurboAssembler : public SharedTurboAssembler {
|
||||
void ExceptionHandler() {}
|
||||
// Define an exception handler and bind a label.
|
||||
void BindExceptionHandler(Label* label) { bind(label); }
|
||||
|
||||
void CallRecordWriteStub(Register object, Register address,
|
||||
RememberedSetAction remembered_set_action,
|
||||
SaveFPRegsMode fp_mode, int builtin_index,
|
||||
Address wasm_target);
|
||||
};
|
||||
|
||||
// MacroAssembler implements a collection of frequently used macros.
|
||||
|
@ -67,7 +67,6 @@ namespace internal {
|
||||
V(ContextOnly) \
|
||||
V(CppBuiltinAdaptor) \
|
||||
V(DynamicCheckMaps) \
|
||||
V(EphemeronKeyBarrier) \
|
||||
V(FastNewObject) \
|
||||
V(ForInPrepare) \
|
||||
V(GetIteratorStackParameter) \
|
||||
@ -96,7 +95,6 @@ namespace internal {
|
||||
V(LoadWithReceiverBaseline) \
|
||||
V(LookupBaseline) \
|
||||
V(NoContext) \
|
||||
V(RecordWrite) \
|
||||
V(ResumeGenerator) \
|
||||
V(SuspendGeneratorBaseline) \
|
||||
V(ResumeGeneratorBaseline) \
|
||||
@ -124,6 +122,7 @@ namespace internal {
|
||||
V(WasmFloat64ToNumber) \
|
||||
V(WasmI32AtomicWait32) \
|
||||
V(WasmI64AtomicWait32) \
|
||||
V(WriteBarrier) \
|
||||
BUILTIN_LIST_TFS(V) \
|
||||
TORQUE_BUILTIN_LIST_TFC(V)
|
||||
|
||||
@ -992,31 +991,14 @@ class FastNewObjectDescriptor
|
||||
static constexpr auto registers();
|
||||
};
|
||||
|
||||
class RecordWriteDescriptor final
|
||||
: public StaticCallInterfaceDescriptor<RecordWriteDescriptor> {
|
||||
class WriteBarrierDescriptor final
|
||||
: public StaticCallInterfaceDescriptor<WriteBarrierDescriptor> {
|
||||
public:
|
||||
DEFINE_PARAMETERS_NO_CONTEXT(kObject, kSlot, kRememberedSet, kFPMode)
|
||||
DEFINE_PARAMETERS_NO_CONTEXT(kObject, kSlotAddress)
|
||||
DEFINE_PARAMETER_TYPES(MachineType::TaggedPointer(), // kObject
|
||||
MachineType::Pointer(), // kSlot
|
||||
MachineType::TaggedSigned(), // kRememberedSet
|
||||
MachineType::TaggedSigned()) // kFPMode
|
||||
|
||||
DECLARE_DESCRIPTOR(RecordWriteDescriptor)
|
||||
|
||||
static constexpr auto registers();
|
||||
static constexpr bool kRestrictAllocatableRegisters = true;
|
||||
};
|
||||
|
||||
class EphemeronKeyBarrierDescriptor final
|
||||
: public StaticCallInterfaceDescriptor<EphemeronKeyBarrierDescriptor> {
|
||||
public:
|
||||
DEFINE_PARAMETERS_NO_CONTEXT(kObject, kSlotAddress, kFPMode)
|
||||
DEFINE_PARAMETER_TYPES(MachineType::TaggedPointer(), // kObject
|
||||
MachineType::Pointer(), // kSlotAddress
|
||||
MachineType::TaggedSigned()) // kFPMode
|
||||
|
||||
DECLARE_DESCRIPTOR(EphemeronKeyBarrierDescriptor)
|
||||
MachineType::Pointer()) // kSlotAddress
|
||||
|
||||
DECLARE_DESCRIPTOR(WriteBarrierDescriptor)
|
||||
static constexpr auto registers();
|
||||
static constexpr bool kRestrictAllocatableRegisters = true;
|
||||
};
|
||||
|
@ -28,8 +28,6 @@ enum AllocationFlags {
|
||||
PRETENURE = 1 << 3,
|
||||
};
|
||||
|
||||
enum class RememberedSetAction { kOmit, kEmit };
|
||||
|
||||
enum class SmiCheck { kOmit, kInline };
|
||||
|
||||
// This is the only place allowed to include the platform-specific headers.
|
||||
|
@ -20,7 +20,7 @@ constexpr auto CallInterfaceDescriptor::DefaultRegisterArray() {
|
||||
}
|
||||
|
||||
// static
|
||||
constexpr auto RecordWriteDescriptor::registers() {
|
||||
constexpr auto WriteBarrierDescriptor::registers() {
|
||||
return RegisterArray(a0, a1, a2, a3, kReturnRegister0);
|
||||
}
|
||||
|
||||
@ -29,11 +29,6 @@ constexpr auto DynamicCheckMapsDescriptor::registers() {
|
||||
return RegisterArray(kReturnRegister0, a0, a1, a2, cp);
|
||||
}
|
||||
|
||||
// static
|
||||
constexpr auto EphemeronKeyBarrierDescriptor::registers() {
|
||||
return RegisterArray(a0, a1, a2, a3, kReturnRegister0);
|
||||
}
|
||||
|
||||
// static
|
||||
constexpr Register LoadDescriptor::ReceiverRegister() { return a1; }
|
||||
// static
|
||||
|
@ -235,17 +235,15 @@ void TurboAssembler::RestoreRegisters(RegList registers) {
|
||||
|
||||
void TurboAssembler::CallEphemeronKeyBarrier(Register object, Register address,
|
||||
SaveFPRegsMode fp_mode) {
|
||||
EphemeronKeyBarrierDescriptor descriptor;
|
||||
WriteBarrierDescriptor descriptor;
|
||||
RegList registers = descriptor.allocatable_registers();
|
||||
|
||||
SaveRegisters(registers);
|
||||
|
||||
Register object_parameter(
|
||||
descriptor.GetRegisterParameter(EphemeronKeyBarrierDescriptor::kObject));
|
||||
Register slot_parameter(descriptor.GetRegisterParameter(
|
||||
EphemeronKeyBarrierDescriptor::kSlotAddress));
|
||||
Register fp_mode_parameter(
|
||||
descriptor.GetRegisterParameter(EphemeronKeyBarrierDescriptor::kFPMode));
|
||||
descriptor.GetRegisterParameter(WriteBarrierDescriptor::kObject));
|
||||
Register slot_parameter(
|
||||
descriptor.GetRegisterParameter(WriteBarrierDescriptor::kSlotAddress));
|
||||
|
||||
Push(object);
|
||||
Push(address);
|
||||
@ -253,50 +251,24 @@ void TurboAssembler::CallEphemeronKeyBarrier(Register object, Register address,
|
||||
Pop(slot_parameter);
|
||||
Pop(object_parameter);
|
||||
|
||||
Move(fp_mode_parameter, Smi::FromEnum(fp_mode));
|
||||
Call(isolate()->builtins()->builtin_handle(Builtins::kEphemeronKeyBarrier),
|
||||
Call(isolate()->builtins()->builtin_handle(
|
||||
Builtins::GetEphemeronKeyBarrierStub(fp_mode)),
|
||||
RelocInfo::CODE_TARGET);
|
||||
RestoreRegisters(registers);
|
||||
}
|
||||
|
||||
void TurboAssembler::CallRecordWriteStub(
|
||||
Register object, Register address,
|
||||
RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode) {
|
||||
CallRecordWriteStub(object, address, remembered_set_action, fp_mode,
|
||||
Builtins::kRecordWrite, kNullAddress);
|
||||
}
|
||||
|
||||
void TurboAssembler::CallRecordWriteStub(
|
||||
Register object, Register address,
|
||||
RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode,
|
||||
Address wasm_target) {
|
||||
CallRecordWriteStub(object, address, remembered_set_action, fp_mode,
|
||||
Builtins::kNoBuiltinId, wasm_target);
|
||||
}
|
||||
|
||||
void TurboAssembler::CallRecordWriteStub(
|
||||
Register object, Register address,
|
||||
RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode,
|
||||
int builtin_index, Address wasm_target) {
|
||||
DCHECK_NE(builtin_index == Builtins::kNoBuiltinId,
|
||||
wasm_target == kNullAddress);
|
||||
// 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.
|
||||
|
||||
RecordWriteDescriptor descriptor;
|
||||
StubCallMode mode) {
|
||||
WriteBarrierDescriptor descriptor;
|
||||
RegList registers = descriptor.allocatable_registers();
|
||||
|
||||
SaveRegisters(registers);
|
||||
Register object_parameter(
|
||||
descriptor.GetRegisterParameter(RecordWriteDescriptor::kObject));
|
||||
descriptor.GetRegisterParameter(WriteBarrierDescriptor::kObject));
|
||||
Register slot_parameter(
|
||||
descriptor.GetRegisterParameter(RecordWriteDescriptor::kSlot));
|
||||
Register remembered_set_parameter(
|
||||
descriptor.GetRegisterParameter(RecordWriteDescriptor::kRememberedSet));
|
||||
Register fp_mode_parameter(
|
||||
descriptor.GetRegisterParameter(RecordWriteDescriptor::kFPMode));
|
||||
descriptor.GetRegisterParameter(WriteBarrierDescriptor::kSlotAddress));
|
||||
|
||||
Push(object);
|
||||
Push(address);
|
||||
@ -304,23 +276,27 @@ void TurboAssembler::CallRecordWriteStub(
|
||||
Pop(slot_parameter);
|
||||
Pop(object_parameter);
|
||||
|
||||
Move(remembered_set_parameter, Smi::FromEnum(remembered_set_action));
|
||||
Move(fp_mode_parameter, Smi::FromEnum(fp_mode));
|
||||
if (builtin_index == Builtins::kNoBuiltinId) {
|
||||
if (mode == StubCallMode::kCallWasmRuntimeStub) {
|
||||
auto wasm_target =
|
||||
wasm::WasmCode::GetRecordWriteStub(remembered_set_action, fp_mode);
|
||||
Call(wasm_target, RelocInfo::WASM_STUB_CALL);
|
||||
} else if (options().inline_offheap_trampolines) {
|
||||
// Inline the trampoline.
|
||||
DCHECK(Builtins::IsBuiltinId(builtin_index));
|
||||
RecordCommentForOffHeapTrampoline(builtin_index);
|
||||
CHECK_NE(builtin_index, Builtins::kNoBuiltinId);
|
||||
EmbeddedData d = EmbeddedData::FromBlob();
|
||||
Address entry = d.InstructionStartOfBuiltin(builtin_index);
|
||||
li(t9, Operand(entry, RelocInfo::OFF_HEAP_TARGET));
|
||||
Call(t9);
|
||||
} else {
|
||||
Handle<Code> code_target =
|
||||
isolate()->builtins()->builtin_handle(Builtins::kRecordWrite);
|
||||
Call(code_target, RelocInfo::CODE_TARGET);
|
||||
auto builtin_index =
|
||||
Builtins::GetRecordWriteStub(remembered_set_action, fp_mode);
|
||||
if (options().inline_offheap_trampolines) {
|
||||
// Inline the trampoline.
|
||||
DCHECK(Builtins::IsBuiltinId(builtin_index));
|
||||
RecordCommentForOffHeapTrampoline(builtin_index);
|
||||
CHECK_NE(builtin_index, Builtins::kNoBuiltinId);
|
||||
EmbeddedData d = EmbeddedData::FromBlob();
|
||||
Address entry = d.InstructionStartOfBuiltin(builtin_index);
|
||||
li(t9, Operand(entry, RelocInfo::OFF_HEAP_TARGET));
|
||||
Call(t9);
|
||||
} else {
|
||||
Handle<Code> code_target =
|
||||
isolate()->builtins()->builtin_handle(builtin_index);
|
||||
Call(code_target, RelocInfo::CODE_TARGET);
|
||||
}
|
||||
}
|
||||
|
||||
RestoreRegisters(registers);
|
||||
|
@ -325,15 +325,14 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
|
||||
void SaveRegisters(RegList registers);
|
||||
void RestoreRegisters(RegList registers);
|
||||
|
||||
void CallRecordWriteStub(Register object, Register address,
|
||||
RememberedSetAction remembered_set_action,
|
||||
SaveFPRegsMode fp_mode);
|
||||
void CallRecordWriteStub(Register object, Register address,
|
||||
RememberedSetAction remembered_set_action,
|
||||
SaveFPRegsMode fp_mode, Address wasm_target);
|
||||
void CallEphemeronKeyBarrier(Register object, Register address,
|
||||
SaveFPRegsMode fp_mode);
|
||||
|
||||
void CallRecordWriteStub(
|
||||
Register object, Register address,
|
||||
RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode,
|
||||
StubCallMode mode = StubCallMode::kCallBuiltinPointer);
|
||||
|
||||
// Push multiple registers on the stack.
|
||||
// Registers are saved in numerical order, with higher numbered registers
|
||||
// saved in higher memory addresses.
|
||||
@ -905,11 +904,6 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
|
||||
|
||||
// Push a fixed frame, consisting of ra, fp.
|
||||
void PushCommonFrame(Register marker_reg = no_reg);
|
||||
|
||||
void CallRecordWriteStub(Register object, Register address,
|
||||
RememberedSetAction remembered_set_action,
|
||||
SaveFPRegsMode fp_mode, int builtin_index,
|
||||
Address wasm_target);
|
||||
};
|
||||
|
||||
// MacroAssembler implements a collection of frequently used macros.
|
||||
|
@ -20,7 +20,7 @@ constexpr auto CallInterfaceDescriptor::DefaultRegisterArray() {
|
||||
}
|
||||
|
||||
// static
|
||||
constexpr auto RecordWriteDescriptor::registers() {
|
||||
constexpr auto WriteBarrierDescriptor::registers() {
|
||||
return RegisterArray(a0, a1, a2, a3, kReturnRegister0);
|
||||
}
|
||||
|
||||
@ -29,11 +29,6 @@ constexpr auto DynamicCheckMapsDescriptor::registers() {
|
||||
return RegisterArray(kReturnRegister0, a0, a1, a2, cp);
|
||||
}
|
||||
|
||||
// static
|
||||
constexpr auto EphemeronKeyBarrierDescriptor::registers() {
|
||||
return RegisterArray(a0, a1, a2, a3, kReturnRegister0);
|
||||
}
|
||||
|
||||
// static
|
||||
constexpr Register LoadDescriptor::ReceiverRegister() { return a1; }
|
||||
// static
|
||||
|
@ -233,17 +233,15 @@ void TurboAssembler::RestoreRegisters(RegList registers) {
|
||||
|
||||
void TurboAssembler::CallEphemeronKeyBarrier(Register object, Register address,
|
||||
SaveFPRegsMode fp_mode) {
|
||||
EphemeronKeyBarrierDescriptor descriptor;
|
||||
WriteBarrierDescriptor descriptor;
|
||||
RegList registers = descriptor.allocatable_registers();
|
||||
|
||||
SaveRegisters(registers);
|
||||
|
||||
Register object_parameter(
|
||||
descriptor.GetRegisterParameter(EphemeronKeyBarrierDescriptor::kObject));
|
||||
Register slot_parameter(descriptor.GetRegisterParameter(
|
||||
EphemeronKeyBarrierDescriptor::kSlotAddress));
|
||||
Register fp_mode_parameter(
|
||||
descriptor.GetRegisterParameter(EphemeronKeyBarrierDescriptor::kFPMode));
|
||||
descriptor.GetRegisterParameter(WriteBarrierDescriptor::kObject));
|
||||
Register slot_parameter(
|
||||
descriptor.GetRegisterParameter(WriteBarrierDescriptor::kSlotAddress));
|
||||
|
||||
Push(object);
|
||||
Push(address);
|
||||
@ -251,50 +249,24 @@ void TurboAssembler::CallEphemeronKeyBarrier(Register object, Register address,
|
||||
Pop(slot_parameter);
|
||||
Pop(object_parameter);
|
||||
|
||||
Move(fp_mode_parameter, Smi::FromEnum(fp_mode));
|
||||
Call(isolate()->builtins()->builtin_handle(Builtins::kEphemeronKeyBarrier),
|
||||
Call(isolate()->builtins()->builtin_handle(
|
||||
Builtins::GetEphemeronKeyBarrierStub(fp_mode)),
|
||||
RelocInfo::CODE_TARGET);
|
||||
RestoreRegisters(registers);
|
||||
}
|
||||
|
||||
void TurboAssembler::CallRecordWriteStub(
|
||||
Register object, Register address,
|
||||
RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode) {
|
||||
CallRecordWriteStub(object, address, remembered_set_action, fp_mode,
|
||||
Builtins::kRecordWrite, kNullAddress);
|
||||
}
|
||||
|
||||
void TurboAssembler::CallRecordWriteStub(
|
||||
Register object, Register address,
|
||||
RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode,
|
||||
Address wasm_target) {
|
||||
CallRecordWriteStub(object, address, remembered_set_action, fp_mode,
|
||||
Builtins::kNoBuiltinId, wasm_target);
|
||||
}
|
||||
|
||||
void TurboAssembler::CallRecordWriteStub(
|
||||
Register object, Register address,
|
||||
RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode,
|
||||
int builtin_index, Address wasm_target) {
|
||||
DCHECK_NE(builtin_index == Builtins::kNoBuiltinId,
|
||||
wasm_target == kNullAddress);
|
||||
// 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.
|
||||
|
||||
RecordWriteDescriptor descriptor;
|
||||
StubCallMode mode) {
|
||||
WriteBarrierDescriptor descriptor;
|
||||
RegList registers = descriptor.allocatable_registers();
|
||||
|
||||
SaveRegisters(registers);
|
||||
|
||||
Register object_parameter(
|
||||
descriptor.GetRegisterParameter(RecordWriteDescriptor::kObject));
|
||||
descriptor.GetRegisterParameter(WriteBarrierDescriptor::kObject));
|
||||
Register slot_parameter(
|
||||
descriptor.GetRegisterParameter(RecordWriteDescriptor::kSlot));
|
||||
Register remembered_set_parameter(
|
||||
descriptor.GetRegisterParameter(RecordWriteDescriptor::kRememberedSet));
|
||||
Register fp_mode_parameter(
|
||||
descriptor.GetRegisterParameter(RecordWriteDescriptor::kFPMode));
|
||||
descriptor.GetRegisterParameter(WriteBarrierDescriptor::kSlotAddress));
|
||||
|
||||
Push(object);
|
||||
Push(address);
|
||||
@ -302,23 +274,27 @@ void TurboAssembler::CallRecordWriteStub(
|
||||
Pop(slot_parameter);
|
||||
Pop(object_parameter);
|
||||
|
||||
Move(remembered_set_parameter, Smi::FromEnum(remembered_set_action));
|
||||
Move(fp_mode_parameter, Smi::FromEnum(fp_mode));
|
||||
if (builtin_index == Builtins::kNoBuiltinId) {
|
||||
if (mode == StubCallMode::kCallWasmRuntimeStub) {
|
||||
auto wasm_target =
|
||||
wasm::WasmCode::GetRecordWriteStub(remembered_set_action, fp_mode);
|
||||
Call(wasm_target, RelocInfo::WASM_STUB_CALL);
|
||||
} else if (options().inline_offheap_trampolines) {
|
||||
// Inline the trampoline.
|
||||
DCHECK(Builtins::IsBuiltinId(builtin_index));
|
||||
RecordCommentForOffHeapTrampoline(builtin_index);
|
||||
CHECK_NE(builtin_index, Builtins::kNoBuiltinId);
|
||||
EmbeddedData d = EmbeddedData::FromBlob();
|
||||
Address entry = d.InstructionStartOfBuiltin(builtin_index);
|
||||
li(t9, Operand(entry, RelocInfo::OFF_HEAP_TARGET));
|
||||
Call(t9);
|
||||
} else {
|
||||
Handle<Code> code_target =
|
||||
isolate()->builtins()->builtin_handle(Builtins::kRecordWrite);
|
||||
Call(code_target, RelocInfo::CODE_TARGET);
|
||||
auto builtin_index =
|
||||
Builtins::GetRecordWriteStub(remembered_set_action, fp_mode);
|
||||
if (options().inline_offheap_trampolines) {
|
||||
// Inline the trampoline.
|
||||
DCHECK(Builtins::IsBuiltinId(builtin_index));
|
||||
RecordCommentForOffHeapTrampoline(builtin_index);
|
||||
CHECK_NE(builtin_index, Builtins::kNoBuiltinId);
|
||||
EmbeddedData d = EmbeddedData::FromBlob();
|
||||
Address entry = d.InstructionStartOfBuiltin(builtin_index);
|
||||
li(t9, Operand(entry, RelocInfo::OFF_HEAP_TARGET));
|
||||
Call(t9);
|
||||
} else {
|
||||
Handle<Code> code_target =
|
||||
isolate()->builtins()->builtin_handle(builtin_index);
|
||||
Call(code_target, RelocInfo::CODE_TARGET);
|
||||
}
|
||||
}
|
||||
|
||||
RestoreRegisters(registers);
|
||||
|
@ -348,15 +348,14 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
|
||||
void SaveRegisters(RegList registers);
|
||||
void RestoreRegisters(RegList registers);
|
||||
|
||||
void CallRecordWriteStub(Register object, Register address,
|
||||
RememberedSetAction remembered_set_action,
|
||||
SaveFPRegsMode fp_mode);
|
||||
void CallRecordWriteStub(Register object, Register address,
|
||||
RememberedSetAction remembered_set_action,
|
||||
SaveFPRegsMode fp_mode, Address wasm_target);
|
||||
void CallEphemeronKeyBarrier(Register object, Register address,
|
||||
SaveFPRegsMode fp_mode);
|
||||
|
||||
void CallRecordWriteStub(
|
||||
Register object, Register address,
|
||||
RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode,
|
||||
StubCallMode mode = StubCallMode::kCallBuiltinPointer);
|
||||
|
||||
// Push multiple registers on the stack.
|
||||
// Registers are saved in numerical order, with higher numbered registers
|
||||
// saved in higher memory addresses.
|
||||
@ -923,11 +922,6 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
|
||||
|
||||
// Push a fixed frame, consisting of ra, fp.
|
||||
void PushCommonFrame(Register marker_reg = no_reg);
|
||||
|
||||
void CallRecordWriteStub(Register object, Register address,
|
||||
RememberedSetAction remembered_set_action,
|
||||
SaveFPRegsMode fp_mode, int builtin_index,
|
||||
Address wasm_target);
|
||||
};
|
||||
|
||||
// MacroAssembler implements a collection of frequently used macros.
|
||||
|
@ -20,7 +20,7 @@ constexpr auto CallInterfaceDescriptor::DefaultRegisterArray() {
|
||||
}
|
||||
|
||||
// static
|
||||
constexpr auto RecordWriteDescriptor::registers() {
|
||||
constexpr auto WriteBarrierDescriptor::registers() {
|
||||
return RegisterArray(r3, r4, r5, r6, r7, kReturnRegister0);
|
||||
}
|
||||
|
||||
@ -29,11 +29,6 @@ constexpr auto DynamicCheckMapsDescriptor::registers() {
|
||||
return RegisterArray(r3, r4, r5, r6, cp);
|
||||
}
|
||||
|
||||
// static
|
||||
constexpr auto EphemeronKeyBarrierDescriptor::registers() {
|
||||
return RegisterArray(r3, r4, r5, r6, r7, kReturnRegister0);
|
||||
}
|
||||
|
||||
// static
|
||||
constexpr Register LoadDescriptor::ReceiverRegister() { return r4; }
|
||||
// static
|
||||
|
@ -653,17 +653,15 @@ void TurboAssembler::RestoreRegisters(RegList registers) {
|
||||
|
||||
void TurboAssembler::CallEphemeronKeyBarrier(Register object, Register address,
|
||||
SaveFPRegsMode fp_mode) {
|
||||
EphemeronKeyBarrierDescriptor descriptor;
|
||||
WriteBarrierDescriptor descriptor;
|
||||
RegList registers = descriptor.allocatable_registers();
|
||||
|
||||
SaveRegisters(registers);
|
||||
|
||||
Register object_parameter(
|
||||
descriptor.GetRegisterParameter(EphemeronKeyBarrierDescriptor::kObject));
|
||||
Register slot_parameter(descriptor.GetRegisterParameter(
|
||||
EphemeronKeyBarrierDescriptor::kSlotAddress));
|
||||
Register fp_mode_parameter(
|
||||
descriptor.GetRegisterParameter(EphemeronKeyBarrierDescriptor::kFPMode));
|
||||
descriptor.GetRegisterParameter(WriteBarrierDescriptor::kObject));
|
||||
Register slot_parameter(
|
||||
descriptor.GetRegisterParameter(WriteBarrierDescriptor::kSlotAddress));
|
||||
|
||||
push(object);
|
||||
push(address);
|
||||
@ -671,51 +669,24 @@ void TurboAssembler::CallEphemeronKeyBarrier(Register object, Register address,
|
||||
pop(slot_parameter);
|
||||
pop(object_parameter);
|
||||
|
||||
Move(fp_mode_parameter, Smi::FromEnum(fp_mode));
|
||||
Call(isolate()->builtins()->builtin_handle(Builtins::kEphemeronKeyBarrier),
|
||||
Call(isolate()->builtins()->builtin_handle(
|
||||
Builtins::GetEphemeronKeyBarrierStub(fp_mode)),
|
||||
RelocInfo::CODE_TARGET);
|
||||
RestoreRegisters(registers);
|
||||
}
|
||||
|
||||
void TurboAssembler::CallRecordWriteStub(
|
||||
Register object, Register address,
|
||||
RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode) {
|
||||
CallRecordWriteStub(object, address, remembered_set_action, fp_mode,
|
||||
Builtins::kRecordWrite, kNullAddress);
|
||||
}
|
||||
|
||||
void TurboAssembler::CallRecordWriteStub(
|
||||
Register object, Register address,
|
||||
RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode,
|
||||
Address wasm_target) {
|
||||
CallRecordWriteStub(object, address, remembered_set_action, fp_mode,
|
||||
Builtins::kNoBuiltinId, wasm_target);
|
||||
}
|
||||
|
||||
void TurboAssembler::CallRecordWriteStub(
|
||||
Register object, Register address,
|
||||
RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode,
|
||||
int builtin_index, Address wasm_target) {
|
||||
DCHECK_NE(builtin_index == Builtins::kNoBuiltinId,
|
||||
wasm_target == kNullAddress);
|
||||
// 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.
|
||||
|
||||
RecordWriteDescriptor descriptor;
|
||||
StubCallMode mode) {
|
||||
WriteBarrierDescriptor descriptor;
|
||||
RegList registers = descriptor.allocatable_registers();
|
||||
|
||||
SaveRegisters(registers);
|
||||
|
||||
Register object_parameter(
|
||||
descriptor.GetRegisterParameter(RecordWriteDescriptor::kObject));
|
||||
descriptor.GetRegisterParameter(WriteBarrierDescriptor::kObject));
|
||||
Register slot_parameter(
|
||||
descriptor.GetRegisterParameter(RecordWriteDescriptor::kSlot));
|
||||
Register remembered_set_parameter(
|
||||
descriptor.GetRegisterParameter(RecordWriteDescriptor::kRememberedSet));
|
||||
Register fp_mode_parameter(
|
||||
descriptor.GetRegisterParameter(RecordWriteDescriptor::kFPMode));
|
||||
descriptor.GetRegisterParameter(WriteBarrierDescriptor::kSlotAddress));
|
||||
|
||||
push(object);
|
||||
push(address);
|
||||
@ -723,22 +694,27 @@ void TurboAssembler::CallRecordWriteStub(
|
||||
pop(slot_parameter);
|
||||
pop(object_parameter);
|
||||
|
||||
Move(remembered_set_parameter, Smi::FromEnum(remembered_set_action));
|
||||
Move(fp_mode_parameter, Smi::FromEnum(fp_mode));
|
||||
if (builtin_index == Builtins::kNoBuiltinId) {
|
||||
if (mode == StubCallMode::kCallWasmRuntimeStub) {
|
||||
// Use {near_call} for direct Wasm call within a module.
|
||||
auto wasm_target =
|
||||
wasm::WasmCode::GetRecordWriteStub(remembered_set_action, fp_mode);
|
||||
Call(wasm_target, RelocInfo::WASM_STUB_CALL);
|
||||
} else if (options().inline_offheap_trampolines) {
|
||||
RecordCommentForOffHeapTrampoline(builtin_index);
|
||||
EmbeddedData d = EmbeddedData::FromBlob();
|
||||
Address entry = d.InstructionStartOfBuiltin(builtin_index);
|
||||
// Use ip directly instead of using UseScratchRegisterScope, as we do
|
||||
// not preserve scratch registers across calls.
|
||||
mov(ip, Operand(entry, RelocInfo::OFF_HEAP_TARGET));
|
||||
Call(ip);
|
||||
} else {
|
||||
Handle<Code> code_target =
|
||||
isolate()->builtins()->builtin_handle(Builtins::kRecordWrite);
|
||||
Call(code_target, RelocInfo::CODE_TARGET);
|
||||
auto builtin_index =
|
||||
Builtins::GetRecordWriteStub(remembered_set_action, fp_mode);
|
||||
if (options().inline_offheap_trampolines) {
|
||||
RecordCommentForOffHeapTrampoline(builtin_index);
|
||||
EmbeddedData d = EmbeddedData::FromBlob();
|
||||
Address entry = d.InstructionStartOfBuiltin(builtin_index);
|
||||
// Use ip directly instead of using UseScratchRegisterScope, as we do
|
||||
// not preserve scratch registers across calls.
|
||||
mov(ip, Operand(entry, RelocInfo::OFF_HEAP_TARGET));
|
||||
Call(ip);
|
||||
} else {
|
||||
Handle<Code> code_target =
|
||||
isolate()->builtins()->builtin_handle(builtin_index);
|
||||
Call(code_target, RelocInfo::CODE_TARGET);
|
||||
}
|
||||
}
|
||||
|
||||
RestoreRegisters(registers);
|
||||
|
@ -284,15 +284,14 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
|
||||
void SaveRegisters(RegList registers);
|
||||
void RestoreRegisters(RegList registers);
|
||||
|
||||
void CallRecordWriteStub(Register object, Register address,
|
||||
RememberedSetAction remembered_set_action,
|
||||
SaveFPRegsMode fp_mode);
|
||||
void CallRecordWriteStub(Register object, Register address,
|
||||
RememberedSetAction remembered_set_action,
|
||||
SaveFPRegsMode fp_mode, Address wasm_target);
|
||||
void CallEphemeronKeyBarrier(Register object, Register address,
|
||||
SaveFPRegsMode fp_mode);
|
||||
|
||||
void CallRecordWriteStub(
|
||||
Register object, Register address,
|
||||
RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode,
|
||||
StubCallMode mode = StubCallMode::kCallBuiltinPointer);
|
||||
|
||||
void MultiPush(RegList regs, Register location = sp);
|
||||
void MultiPop(RegList regs, Register location = sp);
|
||||
|
||||
@ -722,10 +721,6 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
|
||||
void CallCFunctionHelper(Register function, int num_reg_arguments,
|
||||
int num_double_arguments,
|
||||
bool has_function_descriptor);
|
||||
void CallRecordWriteStub(Register object, Register address,
|
||||
RememberedSetAction remembered_set_action,
|
||||
SaveFPRegsMode fp_mode, int builtin_index,
|
||||
Address wasm_target);
|
||||
};
|
||||
|
||||
// MacroAssembler implements a collection of frequently used acros.
|
||||
|
@ -21,7 +21,7 @@ constexpr auto CallInterfaceDescriptor::DefaultRegisterArray() {
|
||||
}
|
||||
|
||||
// static
|
||||
constexpr auto RecordWriteDescriptor::registers() {
|
||||
constexpr auto WriteBarrierDescriptor::registers() {
|
||||
return RegisterArray(a0, a1, a2, a3, kReturnRegister0);
|
||||
}
|
||||
|
||||
@ -30,11 +30,6 @@ constexpr auto DynamicCheckMapsDescriptor::registers() {
|
||||
return RegisterArray(kReturnRegister0, a1, a2, a3, cp);
|
||||
}
|
||||
|
||||
// static
|
||||
constexpr auto EphemeronKeyBarrierDescriptor::registers() {
|
||||
return RegisterArray(a0, a1, a2, a3, kReturnRegister0);
|
||||
}
|
||||
|
||||
// static
|
||||
constexpr Register LoadDescriptor::ReceiverRegister() { return a1; }
|
||||
// static
|
||||
|
@ -234,17 +234,15 @@ void TurboAssembler::RestoreRegisters(RegList registers) {
|
||||
|
||||
void TurboAssembler::CallEphemeronKeyBarrier(Register object, Register address,
|
||||
SaveFPRegsMode fp_mode) {
|
||||
EphemeronKeyBarrierDescriptor descriptor;
|
||||
WriteBarrierDescriptor descriptor;
|
||||
RegList registers = descriptor.allocatable_registers();
|
||||
|
||||
SaveRegisters(registers);
|
||||
|
||||
Register object_parameter(
|
||||
descriptor.GetRegisterParameter(EphemeronKeyBarrierDescriptor::kObject));
|
||||
Register slot_parameter(descriptor.GetRegisterParameter(
|
||||
EphemeronKeyBarrierDescriptor::kSlotAddress));
|
||||
Register fp_mode_parameter(
|
||||
descriptor.GetRegisterParameter(EphemeronKeyBarrierDescriptor::kFPMode));
|
||||
descriptor.GetRegisterParameter(WriteBarrierDescriptor::kObject));
|
||||
Register slot_parameter(
|
||||
descriptor.GetRegisterParameter(WriteBarrierDescriptor::kSlotAddress));
|
||||
|
||||
Push(object);
|
||||
Push(address);
|
||||
@ -252,50 +250,24 @@ void TurboAssembler::CallEphemeronKeyBarrier(Register object, Register address,
|
||||
Pop(slot_parameter);
|
||||
Pop(object_parameter);
|
||||
|
||||
Move(fp_mode_parameter, Smi::FromEnum(fp_mode));
|
||||
Call(isolate()->builtins()->builtin_handle(Builtins::kEphemeronKeyBarrier),
|
||||
Call(isolate()->builtins()->builtin_handle(
|
||||
Builtins::GetEphemeronKeyBarrierStub(fp_mode)),
|
||||
RelocInfo::CODE_TARGET);
|
||||
RestoreRegisters(registers);
|
||||
}
|
||||
|
||||
void TurboAssembler::CallRecordWriteStub(
|
||||
Register object, Register address,
|
||||
RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode) {
|
||||
CallRecordWriteStub(object, address, remembered_set_action, fp_mode,
|
||||
Builtins::kRecordWrite, kNullAddress);
|
||||
}
|
||||
|
||||
void TurboAssembler::CallRecordWriteStub(
|
||||
Register object, Register address,
|
||||
RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode,
|
||||
Address wasm_target) {
|
||||
CallRecordWriteStub(object, address, remembered_set_action, fp_mode,
|
||||
Builtins::kNoBuiltinId, wasm_target);
|
||||
}
|
||||
|
||||
void TurboAssembler::CallRecordWriteStub(
|
||||
Register object, Register address,
|
||||
RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode,
|
||||
int builtin_index, Address wasm_target) {
|
||||
DCHECK_NE(builtin_index == Builtins::kNoBuiltinId,
|
||||
wasm_target == kNullAddress);
|
||||
// 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.
|
||||
|
||||
RecordWriteDescriptor descriptor;
|
||||
StubCallMode mode) {
|
||||
WriteBarrierDescriptor descriptor;
|
||||
RegList registers = descriptor.allocatable_registers();
|
||||
|
||||
SaveRegisters(registers);
|
||||
|
||||
Register object_parameter(
|
||||
descriptor.GetRegisterParameter(RecordWriteDescriptor::kObject));
|
||||
descriptor.GetRegisterParameter(WriteBarrierDescriptor::kObject));
|
||||
Register slot_parameter(
|
||||
descriptor.GetRegisterParameter(RecordWriteDescriptor::kSlot));
|
||||
Register remembered_set_parameter(
|
||||
descriptor.GetRegisterParameter(RecordWriteDescriptor::kRememberedSet));
|
||||
Register fp_mode_parameter(
|
||||
descriptor.GetRegisterParameter(RecordWriteDescriptor::kFPMode));
|
||||
descriptor.GetRegisterParameter(WriteBarrierDescriptor::kSlotAddress));
|
||||
|
||||
Push(object);
|
||||
Push(address);
|
||||
@ -303,27 +275,31 @@ void TurboAssembler::CallRecordWriteStub(
|
||||
Pop(slot_parameter);
|
||||
Pop(object_parameter);
|
||||
|
||||
Move(remembered_set_parameter, Smi::FromEnum(remembered_set_action));
|
||||
Move(fp_mode_parameter, Smi::FromEnum(fp_mode));
|
||||
if (builtin_index == Builtins::kNoBuiltinId) {
|
||||
if (mode == StubCallMode::kCallWasmRuntimeStub) {
|
||||
auto wasm_target =
|
||||
wasm::WasmCode::GetRecordWriteStub(remembered_set_action, fp_mode);
|
||||
Call(wasm_target, RelocInfo::WASM_STUB_CALL);
|
||||
} else if (options().inline_offheap_trampolines) {
|
||||
// Inline the trampoline. //qj
|
||||
DCHECK(Builtins::IsBuiltinId(builtin_index));
|
||||
RecordCommentForOffHeapTrampoline(builtin_index);
|
||||
CHECK_NE(builtin_index, Builtins::kNoBuiltinId);
|
||||
EmbeddedData d = EmbeddedData::FromBlob();
|
||||
Address entry = d.InstructionStartOfBuiltin(builtin_index);
|
||||
|
||||
UseScratchRegisterScope temps(this);
|
||||
BlockTrampolinePoolScope block_trampoline_pool(this);
|
||||
Register scratch = temps.Acquire();
|
||||
li(scratch, Operand(entry, RelocInfo::OFF_HEAP_TARGET));
|
||||
Call(scratch);
|
||||
} else {
|
||||
Handle<Code> code_target =
|
||||
isolate()->builtins()->builtin_handle(Builtins::kRecordWrite);
|
||||
Call(code_target, RelocInfo::CODE_TARGET);
|
||||
auto builtin_index =
|
||||
Builtins::GetRecordWriteStub(remembered_set_action, fp_mode);
|
||||
if (options().inline_offheap_trampolines) {
|
||||
// Inline the trampoline. //qj
|
||||
DCHECK(Builtins::IsBuiltinId(builtin_index));
|
||||
RecordCommentForOffHeapTrampoline(builtin_index);
|
||||
CHECK_NE(builtin_index, Builtins::kNoBuiltinId);
|
||||
EmbeddedData d = EmbeddedData::FromBlob();
|
||||
Address entry = d.InstructionStartOfBuiltin(builtin_index);
|
||||
|
||||
UseScratchRegisterScope temps(this);
|
||||
BlockTrampolinePoolScope block_trampoline_pool(this);
|
||||
Register scratch = temps.Acquire();
|
||||
li(scratch, Operand(entry, RelocInfo::OFF_HEAP_TARGET));
|
||||
Call(scratch);
|
||||
} else {
|
||||
Handle<Code> code_target =
|
||||
isolate()->builtins()->builtin_handle(builtin_index);
|
||||
Call(code_target, RelocInfo::CODE_TARGET);
|
||||
}
|
||||
}
|
||||
|
||||
RestoreRegisters(registers);
|
||||
|
@ -328,15 +328,14 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
|
||||
void SaveRegisters(RegList registers);
|
||||
void RestoreRegisters(RegList registers);
|
||||
|
||||
void CallRecordWriteStub(Register object, Register address,
|
||||
RememberedSetAction remembered_set_action,
|
||||
SaveFPRegsMode fp_mode);
|
||||
void CallRecordWriteStub(Register object, Register address,
|
||||
RememberedSetAction remembered_set_action,
|
||||
SaveFPRegsMode fp_mode, Address wasm_target);
|
||||
void CallEphemeronKeyBarrier(Register object, Register address,
|
||||
SaveFPRegsMode fp_mode);
|
||||
|
||||
void CallRecordWriteStub(
|
||||
Register object, Register address,
|
||||
RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode,
|
||||
StubCallMode mode = StubCallMode::kCallBuiltinPointer);
|
||||
|
||||
// Push multiple registers on the stack.
|
||||
// Registers are saved in numerical order, with higher numbered registers
|
||||
// saved in higher memory addresses.
|
||||
@ -901,11 +900,6 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
|
||||
|
||||
// Push a fixed frame, consisting of ra, fp.
|
||||
void PushCommonFrame(Register marker_reg = no_reg);
|
||||
|
||||
void CallRecordWriteStub(Register object, Register address,
|
||||
RememberedSetAction remembered_set_action,
|
||||
SaveFPRegsMode fp_mode, int builtin_index,
|
||||
Address wasm_target);
|
||||
};
|
||||
|
||||
// MacroAssembler implements a collection of frequently used macros.
|
||||
|
@ -20,7 +20,7 @@ constexpr auto CallInterfaceDescriptor::DefaultRegisterArray() {
|
||||
}
|
||||
|
||||
// static
|
||||
constexpr auto RecordWriteDescriptor::registers() {
|
||||
constexpr auto WriteBarrierDescriptor::registers() {
|
||||
return RegisterArray(r2, r3, r4, r5, r6, kReturnRegister0);
|
||||
}
|
||||
|
||||
@ -28,12 +28,6 @@ constexpr auto RecordWriteDescriptor::registers() {
|
||||
constexpr auto DynamicCheckMapsDescriptor::registers() {
|
||||
return RegisterArray(r2, r3, r4, r5, cp);
|
||||
}
|
||||
|
||||
// static
|
||||
constexpr auto EphemeronKeyBarrierDescriptor::registers() {
|
||||
return RegisterArray(r2, r3, r4, r5, r6, kReturnRegister0);
|
||||
}
|
||||
|
||||
// static
|
||||
constexpr Register LoadDescriptor::ReceiverRegister() { return r3; }
|
||||
// static
|
||||
|
@ -869,17 +869,15 @@ void TurboAssembler::RestoreRegisters(RegList registers) {
|
||||
|
||||
void TurboAssembler::CallEphemeronKeyBarrier(Register object, Register address,
|
||||
SaveFPRegsMode fp_mode) {
|
||||
EphemeronKeyBarrierDescriptor descriptor;
|
||||
WriteBarrierDescriptor descriptor;
|
||||
RegList registers = descriptor.allocatable_registers();
|
||||
|
||||
SaveRegisters(registers);
|
||||
|
||||
Register object_parameter(
|
||||
descriptor.GetRegisterParameter(EphemeronKeyBarrierDescriptor::kObject));
|
||||
Register slot_parameter(descriptor.GetRegisterParameter(
|
||||
EphemeronKeyBarrierDescriptor::kSlotAddress));
|
||||
Register fp_mode_parameter(
|
||||
descriptor.GetRegisterParameter(EphemeronKeyBarrierDescriptor::kFPMode));
|
||||
descriptor.GetRegisterParameter(WriteBarrierDescriptor::kObject));
|
||||
Register slot_parameter(
|
||||
descriptor.GetRegisterParameter(WriteBarrierDescriptor::kSlotAddress));
|
||||
|
||||
Push(object);
|
||||
Push(address);
|
||||
@ -887,50 +885,24 @@ void TurboAssembler::CallEphemeronKeyBarrier(Register object, Register address,
|
||||
Pop(slot_parameter);
|
||||
Pop(object_parameter);
|
||||
|
||||
Move(fp_mode_parameter, Smi::FromEnum(fp_mode));
|
||||
Call(isolate()->builtins()->builtin_handle(Builtins::kEphemeronKeyBarrier),
|
||||
Call(isolate()->builtins()->builtin_handle(
|
||||
Builtins::GetEphemeronKeyBarrierStub(fp_mode)),
|
||||
RelocInfo::CODE_TARGET);
|
||||
RestoreRegisters(registers);
|
||||
}
|
||||
|
||||
void TurboAssembler::CallRecordWriteStub(
|
||||
Register object, Register address,
|
||||
RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode) {
|
||||
CallRecordWriteStub(object, address, remembered_set_action, fp_mode,
|
||||
Builtins::kRecordWrite, kNullAddress);
|
||||
}
|
||||
|
||||
void TurboAssembler::CallRecordWriteStub(
|
||||
Register object, Register address,
|
||||
RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode,
|
||||
Address wasm_target) {
|
||||
CallRecordWriteStub(object, address, remembered_set_action, fp_mode,
|
||||
Builtins::kNoBuiltinId, wasm_target);
|
||||
}
|
||||
|
||||
void TurboAssembler::CallRecordWriteStub(
|
||||
Register object, Register address,
|
||||
RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode,
|
||||
int builtin_index, Address wasm_target) {
|
||||
DCHECK_NE(builtin_index == Builtins::kNoBuiltinId,
|
||||
wasm_target == kNullAddress);
|
||||
// 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.
|
||||
|
||||
RecordWriteDescriptor descriptor;
|
||||
StubCallMode mode) {
|
||||
WriteBarrierDescriptor descriptor;
|
||||
RegList registers = descriptor.allocatable_registers();
|
||||
|
||||
SaveRegisters(registers);
|
||||
|
||||
Register object_parameter(
|
||||
descriptor.GetRegisterParameter(RecordWriteDescriptor::kObject));
|
||||
descriptor.GetRegisterParameter(WriteBarrierDescriptor::kObject));
|
||||
Register slot_parameter(
|
||||
descriptor.GetRegisterParameter(RecordWriteDescriptor::kSlot));
|
||||
Register remembered_set_parameter(
|
||||
descriptor.GetRegisterParameter(RecordWriteDescriptor::kRememberedSet));
|
||||
Register fp_mode_parameter(
|
||||
descriptor.GetRegisterParameter(RecordWriteDescriptor::kFPMode));
|
||||
descriptor.GetRegisterParameter(WriteBarrierDescriptor::kSlotAddress));
|
||||
|
||||
Push(object);
|
||||
Push(address);
|
||||
@ -938,21 +910,25 @@ void TurboAssembler::CallRecordWriteStub(
|
||||
Pop(slot_parameter);
|
||||
Pop(object_parameter);
|
||||
|
||||
Move(remembered_set_parameter, Smi::FromEnum(remembered_set_action));
|
||||
Move(fp_mode_parameter, Smi::FromEnum(fp_mode));
|
||||
if (builtin_index == Builtins::kNoBuiltinId) {
|
||||
if (mode == StubCallMode::kCallWasmRuntimeStub) {
|
||||
auto wasm_target =
|
||||
wasm::WasmCode::GetRecordWriteStub(remembered_set_action, fp_mode);
|
||||
Call(wasm_target, RelocInfo::WASM_STUB_CALL);
|
||||
} else if (options().inline_offheap_trampolines) {
|
||||
RecordCommentForOffHeapTrampoline(builtin_index);
|
||||
CHECK_NE(builtin_index, Builtins::kNoBuiltinId);
|
||||
EmbeddedData d = EmbeddedData::FromBlob();
|
||||
Address entry = d.InstructionStartOfBuiltin(builtin_index);
|
||||
mov(ip, Operand(entry, RelocInfo::OFF_HEAP_TARGET));
|
||||
Call(ip);
|
||||
} else {
|
||||
Handle<Code> code_target =
|
||||
isolate()->builtins()->builtin_handle(Builtins::kRecordWrite);
|
||||
Call(code_target, RelocInfo::CODE_TARGET);
|
||||
auto builtin_index =
|
||||
Builtins::GetRecordWriteStub(remembered_set_action, fp_mode);
|
||||
if (options().inline_offheap_trampolines) {
|
||||
RecordCommentForOffHeapTrampoline(builtin_index);
|
||||
CHECK_NE(builtin_index, Builtins::kNoBuiltinId);
|
||||
EmbeddedData d = EmbeddedData::FromBlob();
|
||||
Address entry = d.InstructionStartOfBuiltin(builtin_index);
|
||||
mov(ip, Operand(entry, RelocInfo::OFF_HEAP_TARGET));
|
||||
Call(ip);
|
||||
} else {
|
||||
Handle<Code> code_target =
|
||||
isolate()->builtins()->builtin_handle(builtin_indexe);
|
||||
Call(code_target, RelocInfo::CODE_TARGET);
|
||||
}
|
||||
}
|
||||
|
||||
RestoreRegisters(registers);
|
||||
|
@ -156,15 +156,14 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
|
||||
void SaveRegisters(RegList registers);
|
||||
void RestoreRegisters(RegList registers);
|
||||
|
||||
void CallRecordWriteStub(Register object, Register address,
|
||||
RememberedSetAction remembered_set_action,
|
||||
SaveFPRegsMode fp_mode);
|
||||
void CallRecordWriteStub(Register object, Register address,
|
||||
RememberedSetAction remembered_set_action,
|
||||
SaveFPRegsMode fp_mode, Address wasm_target);
|
||||
void CallEphemeronKeyBarrier(Register object, Register address,
|
||||
SaveFPRegsMode fp_mode);
|
||||
|
||||
void CallRecordWriteStub(
|
||||
Register object, Register address,
|
||||
RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode,
|
||||
StubCallMode mode = StubCallMode::kCallBuiltinPointer);
|
||||
|
||||
void MultiPush(RegList regs, Register location = sp);
|
||||
void MultiPop(RegList regs, Register location = sp);
|
||||
|
||||
@ -1070,11 +1069,6 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
|
||||
void CallCFunctionHelper(Register function, int num_reg_arguments,
|
||||
int num_double_arguments);
|
||||
|
||||
void CallRecordWriteStub(Register object, Register address,
|
||||
RememberedSetAction remembered_set_action,
|
||||
SaveFPRegsMode fp_mode, int builtin_index,
|
||||
Address wasm_target);
|
||||
|
||||
void Jump(intptr_t target, RelocInfo::Mode rmode, Condition cond = al);
|
||||
int CalculateStackPassedWords(int num_reg_arguments,
|
||||
int num_double_arguments);
|
||||
|
@ -131,6 +131,8 @@ class V8_EXPORT_PRIVATE TurboAssemblerBase : public Assembler {
|
||||
RecordComment(str.str().c_str());
|
||||
}
|
||||
|
||||
enum class RecordWriteCallMode { kDefault, kWasm };
|
||||
|
||||
protected:
|
||||
Isolate* const isolate_ = nullptr;
|
||||
|
||||
|
@ -19,7 +19,7 @@ constexpr auto CallInterfaceDescriptor::DefaultRegisterArray() {
|
||||
}
|
||||
|
||||
// static
|
||||
constexpr auto RecordWriteDescriptor::registers() {
|
||||
constexpr auto WriteBarrierDescriptor::registers() {
|
||||
return RegisterArray(arg_reg_1, arg_reg_2, arg_reg_3, arg_reg_4,
|
||||
kReturnRegister0);
|
||||
}
|
||||
@ -30,12 +30,6 @@ constexpr auto DynamicCheckMapsDescriptor::registers() {
|
||||
kRuntimeCallFunctionRegister, kContextRegister);
|
||||
}
|
||||
|
||||
// static
|
||||
constexpr auto EphemeronKeyBarrierDescriptor::registers() {
|
||||
return RegisterArray(arg_reg_1, arg_reg_2, arg_reg_3, arg_reg_4,
|
||||
kReturnRegister0);
|
||||
}
|
||||
|
||||
// static
|
||||
constexpr Register LoadDescriptor::ReceiverRegister() { return rdx; }
|
||||
// static
|
||||
|
@ -409,85 +409,56 @@ void TurboAssembler::RestoreRegisters(RegList registers) {
|
||||
|
||||
void TurboAssembler::CallEphemeronKeyBarrier(Register object, Register address,
|
||||
SaveFPRegsMode fp_mode) {
|
||||
EphemeronKeyBarrierDescriptor descriptor;
|
||||
WriteBarrierDescriptor descriptor;
|
||||
RegList registers = descriptor.allocatable_registers();
|
||||
|
||||
SaveRegisters(registers);
|
||||
|
||||
Register object_parameter(
|
||||
descriptor.GetRegisterParameter(EphemeronKeyBarrierDescriptor::kObject));
|
||||
Register slot_parameter(descriptor.GetRegisterParameter(
|
||||
EphemeronKeyBarrierDescriptor::kSlotAddress));
|
||||
Register fp_mode_parameter(
|
||||
descriptor.GetRegisterParameter(EphemeronKeyBarrierDescriptor::kFPMode));
|
||||
descriptor.GetRegisterParameter(WriteBarrierDescriptor::kObject));
|
||||
Register slot_parameter(
|
||||
descriptor.GetRegisterParameter(WriteBarrierDescriptor::kSlotAddress));
|
||||
|
||||
MovePair(slot_parameter, address, object_parameter, object);
|
||||
Smi smi_fm = Smi::FromEnum(fp_mode);
|
||||
Move(fp_mode_parameter, smi_fm);
|
||||
Call(isolate()->builtins()->builtin_handle(Builtins::kEphemeronKeyBarrier),
|
||||
Call(isolate()->builtins()->builtin_handle(
|
||||
Builtins::GetEphemeronKeyBarrierStub(fp_mode)),
|
||||
RelocInfo::CODE_TARGET);
|
||||
|
||||
RestoreRegisters(registers);
|
||||
}
|
||||
|
||||
void TurboAssembler::CallRecordWriteStub(
|
||||
Register object, Register address,
|
||||
RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode) {
|
||||
CallRecordWriteStub(object, address, remembered_set_action, fp_mode,
|
||||
Builtins::kRecordWrite, kNullAddress);
|
||||
}
|
||||
|
||||
void TurboAssembler::CallRecordWriteStub(
|
||||
Register object, Register address,
|
||||
RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode,
|
||||
Address wasm_target) {
|
||||
CallRecordWriteStub(object, address, remembered_set_action, fp_mode,
|
||||
Builtins::kNoBuiltinId, wasm_target);
|
||||
}
|
||||
|
||||
void TurboAssembler::CallRecordWriteStub(
|
||||
Register object, Register address,
|
||||
RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode,
|
||||
int builtin_index, Address wasm_target) {
|
||||
DCHECK_NE(builtin_index == Builtins::kNoBuiltinId,
|
||||
wasm_target == kNullAddress);
|
||||
|
||||
RecordWriteDescriptor descriptor;
|
||||
StubCallMode mode) {
|
||||
WriteBarrierDescriptor descriptor;
|
||||
RegList registers = descriptor.allocatable_registers();
|
||||
|
||||
SaveRegisters(registers);
|
||||
|
||||
Register object_parameter(
|
||||
descriptor.GetRegisterParameter(RecordWriteDescriptor::kObject));
|
||||
descriptor.GetRegisterParameter(WriteBarrierDescriptor::kObject));
|
||||
Register slot_parameter(
|
||||
descriptor.GetRegisterParameter(RecordWriteDescriptor::kSlot));
|
||||
Register remembered_set_parameter(
|
||||
descriptor.GetRegisterParameter(RecordWriteDescriptor::kRememberedSet));
|
||||
Register fp_mode_parameter(
|
||||
descriptor.GetRegisterParameter(RecordWriteDescriptor::kFPMode));
|
||||
descriptor.GetRegisterParameter(WriteBarrierDescriptor::kSlotAddress));
|
||||
|
||||
// Prepare argument registers for calling RecordWrite
|
||||
// slot_parameter <= address
|
||||
// object_parameter <= object
|
||||
MovePair(slot_parameter, address, object_parameter, object);
|
||||
|
||||
Smi smi_rsa = Smi::FromEnum(remembered_set_action);
|
||||
Smi smi_fm = Smi::FromEnum(fp_mode);
|
||||
Move(remembered_set_parameter, smi_rsa);
|
||||
if (smi_rsa != smi_fm) {
|
||||
Move(fp_mode_parameter, smi_fm);
|
||||
} else {
|
||||
movq(fp_mode_parameter, remembered_set_parameter);
|
||||
}
|
||||
if (builtin_index == Builtins::kNoBuiltinId) {
|
||||
if (mode == StubCallMode::kCallWasmRuntimeStub) {
|
||||
// Use {near_call} for direct Wasm call within a module.
|
||||
auto wasm_target =
|
||||
wasm::WasmCode::GetRecordWriteStub(remembered_set_action, fp_mode);
|
||||
near_call(wasm_target, RelocInfo::WASM_STUB_CALL);
|
||||
} else if (options().inline_offheap_trampolines) {
|
||||
CallBuiltin(builtin_index);
|
||||
} else {
|
||||
Handle<Code> code_target =
|
||||
isolate()->builtins()->builtin_handle(Builtins::kRecordWrite);
|
||||
Call(code_target, RelocInfo::CODE_TARGET);
|
||||
auto builtin_index =
|
||||
Builtins::GetRecordWriteStub(remembered_set_action, fp_mode);
|
||||
if (options().inline_offheap_trampolines) {
|
||||
CallBuiltin(builtin_index);
|
||||
} else {
|
||||
Handle<Code> code_target =
|
||||
isolate()->builtins()->builtin_handle(builtin_index);
|
||||
Call(code_target, RelocInfo::CODE_TARGET);
|
||||
}
|
||||
}
|
||||
|
||||
RestoreRegisters(registers);
|
||||
|
@ -504,15 +504,14 @@ class V8_EXPORT_PRIVATE TurboAssembler : public SharedTurboAssembler {
|
||||
void SaveRegisters(RegList registers);
|
||||
void RestoreRegisters(RegList registers);
|
||||
|
||||
void CallRecordWriteStub(Register object, Register address,
|
||||
RememberedSetAction remembered_set_action,
|
||||
SaveFPRegsMode fp_mode);
|
||||
void CallRecordWriteStub(Register object, Register address,
|
||||
RememberedSetAction remembered_set_action,
|
||||
SaveFPRegsMode fp_mode, Address wasm_target);
|
||||
void CallEphemeronKeyBarrier(Register object, Register address,
|
||||
SaveFPRegsMode fp_mode);
|
||||
|
||||
void CallRecordWriteStub(
|
||||
Register object, Register address,
|
||||
RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode,
|
||||
StubCallMode mode = StubCallMode::kCallBuiltinPointer);
|
||||
|
||||
void MoveNumber(Register dst, double value);
|
||||
void MoveNonSmi(Register dst, double value);
|
||||
|
||||
@ -611,11 +610,6 @@ class V8_EXPORT_PRIVATE TurboAssembler : public SharedTurboAssembler {
|
||||
// Returns a register holding the smi value. The register MUST NOT be
|
||||
// modified. It may be the "smi 1 constant" register.
|
||||
Register GetSmiConstant(Smi value);
|
||||
|
||||
void CallRecordWriteStub(Register object, Register address,
|
||||
RememberedSetAction remembered_set_action,
|
||||
SaveFPRegsMode fp_mode, int builtin_index,
|
||||
Address wasm_target);
|
||||
};
|
||||
|
||||
// MacroAssembler implements a collection of frequently used macros.
|
||||
|
@ -468,6 +468,8 @@ enum class StoreOrigin { kMaybeKeyed, kNamed };
|
||||
|
||||
enum class TypeofMode { kInside, kNotInside };
|
||||
|
||||
// Use by RecordWrite stubs.
|
||||
enum class RememberedSetAction { kOmit, kEmit };
|
||||
// Enums used by CEntry.
|
||||
enum class SaveFPRegsMode { kIgnore, kSave };
|
||||
enum class ArgvMode { kStack, kRegister };
|
||||
|
@ -212,7 +212,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
|
||||
#if V8_ENABLE_WEBASSEMBLY
|
||||
} else if (stub_mode_ == StubCallMode::kCallWasmRuntimeStub) {
|
||||
__ CallRecordWriteStub(object_, offset_, remembered_set_action,
|
||||
save_fp_mode, wasm::WasmCode::kRecordWrite);
|
||||
save_fp_mode, StubCallMode::kCallWasmRuntimeStub);
|
||||
#endif // V8_ENABLE_WEBASSEMBLY
|
||||
} else {
|
||||
__ CallRecordWriteStub(object_, offset_, remembered_set_action,
|
||||
|
@ -306,7 +306,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
|
||||
// Just encode the stub index. This will be patched when the code
|
||||
// is added to the native module and copied into wasm code space.
|
||||
__ CallRecordWriteStub(object_, offset_, remembered_set_action,
|
||||
save_fp_mode, wasm::WasmCode::kRecordWrite);
|
||||
save_fp_mode, StubCallMode::kCallWasmRuntimeStub);
|
||||
#endif // V8_ENABLE_WEBASSEMBLY
|
||||
} else {
|
||||
__ CallRecordWriteStub(object_, offset_, remembered_set_action,
|
||||
|
@ -338,7 +338,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
|
||||
// Just encode the stub index. This will be patched when the code
|
||||
// is added to the native module and copied into wasm code space.
|
||||
__ CallRecordWriteStub(object_, scratch1_, remembered_set_action,
|
||||
save_fp_mode, wasm::WasmCode::kRecordWrite);
|
||||
save_fp_mode, StubCallMode::kCallWasmRuntimeStub);
|
||||
} else {
|
||||
#endif // V8_ENABLE_WEBASSEMBLY
|
||||
__ CallRecordWriteStub(object_, scratch1_, remembered_set_action,
|
||||
|
@ -184,7 +184,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
|
||||
// Just encode the stub index. This will be patched when the code
|
||||
// is added to the native module and copied into wasm code space.
|
||||
__ CallRecordWriteStub(object_, scratch1_, remembered_set_action,
|
||||
save_fp_mode, wasm::WasmCode::kRecordWrite);
|
||||
save_fp_mode, StubCallMode::kCallWasmRuntimeStub);
|
||||
#endif // V8_ENABLE_WEBASSEMBLY
|
||||
} else {
|
||||
__ CallRecordWriteStub(object_, scratch1_, remembered_set_action,
|
||||
|
@ -185,7 +185,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
|
||||
// Just encode the stub index. This will be patched when the code
|
||||
// is added to the native module and copied into wasm code space.
|
||||
__ CallRecordWriteStub(object_, scratch1_, remembered_set_action,
|
||||
save_fp_mode, wasm::WasmCode::kRecordWrite);
|
||||
save_fp_mode, StubCallMode::kCallWasmRuntimeStub);
|
||||
#endif // V8_ENABLE_WEBASSEMBLY
|
||||
} else {
|
||||
__ CallRecordWriteStub(object_, scratch1_, remembered_set_action,
|
||||
|
@ -200,7 +200,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
|
||||
#if V8_ENABLE_WEBASSEMBLY
|
||||
} else if (stub_mode_ == StubCallMode::kCallWasmRuntimeStub) {
|
||||
__ CallRecordWriteStub(object_, scratch1_, remembered_set_action,
|
||||
save_fp_mode, wasm::WasmCode::kRecordWrite);
|
||||
save_fp_mode, StubCallMode::kCallWasmRuntimeStub);
|
||||
#endif // V8_ENABLE_WEBASSEMBLY
|
||||
} else {
|
||||
__ CallRecordWriteStub(object_, scratch1_, remembered_set_action,
|
||||
|
@ -178,7 +178,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
|
||||
// Just encode the stub index. This will be patched when the code
|
||||
// is added to the native module and copied into wasm code space.
|
||||
__ CallRecordWriteStub(object_, scratch1_, remembered_set_action,
|
||||
save_fp_mode, wasm::WasmCode::kRecordWrite);
|
||||
save_fp_mode, StubCallMode::kCallWasmRuntimeStub);
|
||||
} else {
|
||||
__ CallRecordWriteStub(object_, scratch1_, remembered_set_action,
|
||||
save_fp_mode);
|
||||
|
@ -234,7 +234,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
|
||||
#if V8_ENABLE_WEBASSEMBLY
|
||||
} else if (stub_mode_ == StubCallMode::kCallWasmRuntimeStub) {
|
||||
__ CallRecordWriteStub(object_, scratch1_, remembered_set_action,
|
||||
save_fp_mode, wasm::WasmCode::kRecordWrite);
|
||||
save_fp_mode, StubCallMode::kCallWasmRuntimeStub);
|
||||
#endif // V8_ENABLE_WEBASSEMBLY
|
||||
} else {
|
||||
__ CallRecordWriteStub(object_, scratch1_, remembered_set_action,
|
||||
|
@ -299,7 +299,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
|
||||
// Just encode the stub index. This will be patched when the code
|
||||
// is added to the native module and copied into wasm code space.
|
||||
__ CallRecordWriteStub(object_, scratch1_, remembered_set_action,
|
||||
save_fp_mode, wasm::WasmCode::kRecordWrite);
|
||||
save_fp_mode, StubCallMode::kCallWasmRuntimeStub);
|
||||
#endif // V8_ENABLE_WEBASSEMBLY
|
||||
} else {
|
||||
__ CallRecordWriteStub(object_, scratch1_, remembered_set_action,
|
||||
|
@ -1039,7 +1039,10 @@ static bool TransitivelyCalledBuiltinHasNoSideEffect(Builtins::Name caller,
|
||||
case Builtins::kProxyHasProperty:
|
||||
case Builtins::kProxyIsExtensible:
|
||||
case Builtins::kProxyGetPrototypeOf:
|
||||
case Builtins::kRecordWrite:
|
||||
case Builtins::kRecordWriteEmitRememberedSetSaveFP:
|
||||
case Builtins::kRecordWriteOmitRememberedSetSaveFP:
|
||||
case Builtins::kRecordWriteEmitRememberedSetIgnoreFP:
|
||||
case Builtins::kRecordWriteOmitRememberedSetIgnoreFP:
|
||||
case Builtins::kStringAdd_CheckNone:
|
||||
case Builtins::kStringEqual:
|
||||
case Builtins::kStringIndexOf:
|
||||
|
@ -78,7 +78,7 @@ int WriteBarrier::MarkingFromCode(Address raw_host, Address raw_slot) {
|
||||
}
|
||||
#endif
|
||||
WriteBarrier::Marking(host, slot, MaybeObject(value));
|
||||
// Called by RecordWriteCodeStubAssembler, which doesnt accept void type
|
||||
// Called by WriteBarrierCodeStubAssembler, which doesnt accept void type
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -101,7 +101,10 @@ bool IsUnexpectedCodeObject(Isolate* isolate, HeapObject obj) {
|
||||
case Builtins::kAbort:
|
||||
case Builtins::kCEntry_Return1_DontSaveFPRegs_ArgvOnStack_NoBuiltinExit:
|
||||
case Builtins::kInterpreterEntryTrampoline:
|
||||
case Builtins::kRecordWrite:
|
||||
case Builtins::kRecordWriteEmitRememberedSetSaveFP:
|
||||
case Builtins::kRecordWriteOmitRememberedSetSaveFP:
|
||||
case Builtins::kRecordWriteEmitRememberedSetIgnoreFP:
|
||||
case Builtins::kRecordWriteOmitRememberedSetIgnoreFP:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
|
@ -761,7 +761,7 @@ void LiftoffAssembler::StoreTaggedPointer(Register dst_addr,
|
||||
actual_offset_reg == no_reg ? Operand(offset_imm)
|
||||
: Operand(actual_offset_reg),
|
||||
RememberedSetAction::kEmit, SaveFPRegsMode::kSave,
|
||||
wasm::WasmCode::kRecordWrite);
|
||||
StubCallMode::kCallWasmRuntimeStub);
|
||||
bind(&exit);
|
||||
}
|
||||
|
||||
|
@ -486,7 +486,7 @@ void LiftoffAssembler::StoreTaggedPointer(Register dst_addr,
|
||||
? Operand(dst_op.regoffset().X())
|
||||
: Operand(dst_op.offset()),
|
||||
RememberedSetAction::kEmit, SaveFPRegsMode::kSave,
|
||||
wasm::WasmCode::kRecordWrite);
|
||||
StubCallMode::kCallWasmRuntimeStub);
|
||||
bind(&exit);
|
||||
}
|
||||
|
||||
|
@ -383,7 +383,8 @@ void LiftoffAssembler::StoreTaggedPointer(Register dst_addr,
|
||||
Label::kNear);
|
||||
lea(scratch, dst_op);
|
||||
CallRecordWriteStub(dst_addr, scratch, RememberedSetAction::kEmit,
|
||||
SaveFPRegsMode::kSave, wasm::WasmCode::kRecordWrite);
|
||||
SaveFPRegsMode::kSave,
|
||||
StubCallMode::kCallWasmRuntimeStub);
|
||||
bind(&exit);
|
||||
}
|
||||
|
||||
|
@ -486,7 +486,8 @@ void LiftoffAssembler::StoreTaggedPointer(Register dst_addr,
|
||||
MemoryChunk::kPointersToHereAreInterestingMask, eq, &exit);
|
||||
Addu(scratch, dst_op.rm(), dst_op.offset());
|
||||
CallRecordWriteStub(dst_addr, scratch, RememberedSetAction::kEmit,
|
||||
SaveFPRegsMode::kSave, wasm::WasmCode::kRecordWrite);
|
||||
SaveFPRegsMode::kSave,
|
||||
StubCallMode::kCallWasmRuntimeStub);
|
||||
bind(&exit);
|
||||
}
|
||||
|
||||
|
@ -465,7 +465,8 @@ void LiftoffAssembler::StoreTaggedPointer(Register dst_addr,
|
||||
&exit);
|
||||
Daddu(scratch, dst_op.rm(), dst_op.offset());
|
||||
CallRecordWriteStub(dst_addr, scratch, RememberedSetAction::kEmit,
|
||||
SaveFPRegsMode::kSave, wasm::WasmCode::kRecordWrite);
|
||||
SaveFPRegsMode::kSave,
|
||||
StubCallMode::kCallWasmRuntimeStub);
|
||||
bind(&exit);
|
||||
}
|
||||
|
||||
|
@ -454,7 +454,8 @@ void LiftoffAssembler::StoreTaggedPointer(Register dst_addr,
|
||||
MemoryChunk::kPointersToHereAreInterestingMask, eq, &exit);
|
||||
Add64(scratch, dst_op.rm(), dst_op.offset());
|
||||
CallRecordWriteStub(dst_addr, scratch, RememberedSetAction::kEmit,
|
||||
SaveFPRegsMode::kSave, wasm::WasmCode::kRecordWrite);
|
||||
SaveFPRegsMode::kSave,
|
||||
StubCallMode::kCallWasmRuntimeStub);
|
||||
bind(&exit);
|
||||
}
|
||||
|
||||
|
@ -272,7 +272,8 @@ void LiftoffAssembler::StoreTaggedPointer(Register dst_addr,
|
||||
eq, &exit);
|
||||
lay(r1, dst_op);
|
||||
CallRecordWriteStub(dst_addr, r1, RememberedSetAction::kEmit,
|
||||
SaveFPRegsMode::kSave, wasm::WasmCode::kRecordWrite);
|
||||
SaveFPRegsMode::kSave,
|
||||
StubCallMode::kCallWasmRuntimeStub);
|
||||
bind(&exit);
|
||||
}
|
||||
|
||||
|
@ -382,7 +382,8 @@ void LiftoffAssembler::StoreTaggedPointer(Register dst_addr,
|
||||
Label::kNear);
|
||||
leaq(scratch, dst_op);
|
||||
CallRecordWriteStub(dst_addr, scratch, RememberedSetAction::kEmit,
|
||||
SaveFPRegsMode::kSave, wasm::WasmCode::kRecordWrite);
|
||||
SaveFPRegsMode::kSave,
|
||||
StubCallMode::kCallWasmRuntimeStub);
|
||||
bind(&exit);
|
||||
}
|
||||
|
||||
|
@ -51,51 +51,54 @@ struct WasmModule;
|
||||
|
||||
// Convenience macro listing all wasm runtime stubs. Note that the first few
|
||||
// elements of the list coincide with {compiler::TrapId}, order matters.
|
||||
#define WASM_RUNTIME_STUB_LIST(V, VTRAP) \
|
||||
FOREACH_WASM_TRAPREASON(VTRAP) \
|
||||
V(WasmCompileLazy) \
|
||||
V(WasmTriggerTierUp) \
|
||||
V(WasmDebugBreak) \
|
||||
V(WasmInt32ToHeapNumber) \
|
||||
V(WasmTaggedNonSmiToInt32) \
|
||||
V(WasmFloat32ToNumber) \
|
||||
V(WasmFloat64ToNumber) \
|
||||
V(WasmTaggedToFloat64) \
|
||||
V(WasmAllocateJSArray) \
|
||||
V(WasmAllocatePair) \
|
||||
V(WasmAtomicNotify) \
|
||||
V(WasmI32AtomicWait32) \
|
||||
V(WasmI32AtomicWait64) \
|
||||
V(WasmI64AtomicWait32) \
|
||||
V(WasmI64AtomicWait64) \
|
||||
V(WasmGetOwnProperty) \
|
||||
V(WasmRefFunc) \
|
||||
V(WasmMemoryGrow) \
|
||||
V(WasmTableInit) \
|
||||
V(WasmTableCopy) \
|
||||
V(WasmTableFill) \
|
||||
V(WasmTableGrow) \
|
||||
V(WasmTableGet) \
|
||||
V(WasmTableSet) \
|
||||
V(WasmStackGuard) \
|
||||
V(WasmStackOverflow) \
|
||||
V(WasmAllocateFixedArray) \
|
||||
V(WasmThrow) \
|
||||
V(WasmRethrow) \
|
||||
V(WasmTraceEnter) \
|
||||
V(WasmTraceExit) \
|
||||
V(WasmTraceMemory) \
|
||||
V(BigIntToI32Pair) \
|
||||
V(BigIntToI64) \
|
||||
V(DoubleToI) \
|
||||
V(I32PairToBigInt) \
|
||||
V(I64ToBigInt) \
|
||||
V(RecordWrite) \
|
||||
V(ToNumber) \
|
||||
V(WasmAllocateArrayWithRtt) \
|
||||
V(WasmAllocateRtt) \
|
||||
V(WasmAllocateStructWithRtt) \
|
||||
V(WasmSubtypeCheck) \
|
||||
#define WASM_RUNTIME_STUB_LIST(V, VTRAP) \
|
||||
FOREACH_WASM_TRAPREASON(VTRAP) \
|
||||
V(WasmCompileLazy) \
|
||||
V(WasmTriggerTierUp) \
|
||||
V(WasmDebugBreak) \
|
||||
V(WasmInt32ToHeapNumber) \
|
||||
V(WasmTaggedNonSmiToInt32) \
|
||||
V(WasmFloat32ToNumber) \
|
||||
V(WasmFloat64ToNumber) \
|
||||
V(WasmTaggedToFloat64) \
|
||||
V(WasmAllocateJSArray) \
|
||||
V(WasmAllocatePair) \
|
||||
V(WasmAtomicNotify) \
|
||||
V(WasmI32AtomicWait32) \
|
||||
V(WasmI32AtomicWait64) \
|
||||
V(WasmI64AtomicWait32) \
|
||||
V(WasmI64AtomicWait64) \
|
||||
V(WasmGetOwnProperty) \
|
||||
V(WasmRefFunc) \
|
||||
V(WasmMemoryGrow) \
|
||||
V(WasmTableInit) \
|
||||
V(WasmTableCopy) \
|
||||
V(WasmTableFill) \
|
||||
V(WasmTableGrow) \
|
||||
V(WasmTableGet) \
|
||||
V(WasmTableSet) \
|
||||
V(WasmStackGuard) \
|
||||
V(WasmStackOverflow) \
|
||||
V(WasmAllocateFixedArray) \
|
||||
V(WasmThrow) \
|
||||
V(WasmRethrow) \
|
||||
V(WasmTraceEnter) \
|
||||
V(WasmTraceExit) \
|
||||
V(WasmTraceMemory) \
|
||||
V(BigIntToI32Pair) \
|
||||
V(BigIntToI64) \
|
||||
V(DoubleToI) \
|
||||
V(I32PairToBigInt) \
|
||||
V(I64ToBigInt) \
|
||||
V(RecordWriteEmitRememberedSetSaveFP) \
|
||||
V(RecordWriteOmitRememberedSetSaveFP) \
|
||||
V(RecordWriteEmitRememberedSetIgnoreFP) \
|
||||
V(RecordWriteOmitRememberedSetIgnoreFP) \
|
||||
V(ToNumber) \
|
||||
V(WasmAllocateArrayWithRtt) \
|
||||
V(WasmAllocateRtt) \
|
||||
V(WasmAllocateStructWithRtt) \
|
||||
V(WasmSubtypeCheck) \
|
||||
V(WasmOnStackReplace)
|
||||
|
||||
// Sorted, disjoint and non-overlapping memory regions. A region is of the
|
||||
@ -148,6 +151,27 @@ class V8_EXPORT_PRIVATE WasmCode final {
|
||||
kRuntimeStubCount
|
||||
};
|
||||
|
||||
static constexpr RuntimeStubId GetRecordWriteStub(
|
||||
RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode) {
|
||||
switch (remembered_set_action) {
|
||||
case RememberedSetAction::kEmit:
|
||||
switch (fp_mode) {
|
||||
case SaveFPRegsMode::kIgnore:
|
||||
return RuntimeStubId::kRecordWriteEmitRememberedSetIgnoreFP;
|
||||
case SaveFPRegsMode::kSave:
|
||||
return RuntimeStubId::kRecordWriteEmitRememberedSetSaveFP;
|
||||
}
|
||||
case RememberedSetAction::kOmit:
|
||||
switch (fp_mode) {
|
||||
case SaveFPRegsMode::kIgnore:
|
||||
return RuntimeStubId::kRecordWriteOmitRememberedSetIgnoreFP;
|
||||
case SaveFPRegsMode::kSave:
|
||||
return RuntimeStubId::kRecordWriteOmitRememberedSetSaveFP;
|
||||
}
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
Vector<byte> instructions() const {
|
||||
return VectorOf(instructions_, static_cast<size_t>(instructions_size_));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user