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