Skip to content

Commit 0523061

Browse files
pthierV8 LUCI CQ
authored andcommitted
[masm] Add quick check for RO values to write barrier
With static roots we can use a simple comparison with an immediate to check if a value is in RO space. As this is very cheap, we add this check before loading the page flags. Bug: 364466897 Change-Id: Idae9ccde32440a6c869f2f69754a494f7ac98e9a Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/5836877 Commit-Queue: Patrick Thier <[email protected]> Reviewed-by: Nico Hartmann <[email protected]> Cr-Commit-Position: refs/heads/main@{#95970}
1 parent 55f943e commit 0523061

6 files changed

Lines changed: 76 additions & 20 deletions

File tree

src/codegen/arm64/macro-assembler-arm64-inl.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1230,6 +1230,11 @@ void MacroAssembler::JumpIfLessThan(Register x, int32_t y, Label* dest) {
12301230
CompareAndBranch(x, y, lt, dest);
12311231
}
12321232

1233+
void MacroAssembler::JumpIfUnsignedLessThan(Register x, int32_t y,
1234+
Label* dest) {
1235+
CompareAndBranch(x, y, lo, dest);
1236+
}
1237+
12331238
void MacroAssembler::JumpIfNotSmi(Register value, Label* not_smi_label) {
12341239
JumpIfSmi(value, nullptr, not_smi_label);
12351240
}

src/codegen/arm64/macro-assembler-arm64.cc

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1501,7 +1501,7 @@ void MacroAssembler::ReplaceClosureCodeWithOptimizedCode(
15011501
FieldMemOperand(closure, JSFunction::kCodeOffset));
15021502
RecordWriteField(closure, JSFunction::kCodeOffset, optimized_code,
15031503
kLRHasNotBeenSaved, SaveFPRegsMode::kIgnore, SmiCheck::kOmit,
1504-
SlotDescriptor::ForCodePointerSlot());
1504+
ReadOnlyCheck::kOmit, SlotDescriptor::ForCodePointerSlot());
15051505
#endif // V8_ENABLE_LEAPTIERING
15061506
}
15071507

@@ -3614,17 +3614,24 @@ void MacroAssembler::JumpIfNotMarking(Label* not_marking,
36143614
Cbz(scratch, not_marking);
36153615
}
36163616

3617-
void MacroAssembler::RecordWriteField(Register object, int offset,
3618-
Register value,
3619-
LinkRegisterStatus lr_status,
3620-
SaveFPRegsMode save_fp,
3621-
SmiCheck smi_check, SlotDescriptor slot) {
3617+
void MacroAssembler::RecordWriteField(
3618+
Register object, int offset, Register value, LinkRegisterStatus lr_status,
3619+
SaveFPRegsMode save_fp, SmiCheck smi_check, ReadOnlyCheck ro_check,
3620+
SlotDescriptor slot) {
36223621
ASM_CODE_COMMENT(this);
36233622
DCHECK(!AreAliased(object, value));
36243623
// First, check if a write barrier is even needed. The tests below
3625-
// catch stores of Smis.
3624+
// catch stores of Smis and read-only objects.
36263625
Label done;
36273626

3627+
#if V8_STATIC_ROOTS_BOOL
3628+
if (ro_check == ReadOnlyCheck::kInline) {
3629+
// Quick check for Read-only and small Smi values.
3630+
static_assert(StaticReadOnlyRoot::kLastAllocatedRoot < kRegularPageSize);
3631+
JumpIfUnsignedLessThan(value, kRegularPageSize, &done);
3632+
}
3633+
#endif // V8_STATIC_ROOTS_BOOL
3634+
36283635
// Skip the barrier if writing a smi.
36293636
if (smi_check == SmiCheck::kInline) {
36303637
JumpIfSmi(value, &done);
@@ -3648,7 +3655,7 @@ void MacroAssembler::RecordWriteField(Register object, int offset,
36483655
}
36493656

36503657
RecordWrite(object, Operand(offset - kHeapObjectTag), value, lr_status,
3651-
save_fp, SmiCheck::kOmit, slot);
3658+
save_fp, SmiCheck::kOmit, ReadOnlyCheck::kOmit, slot);
36523659

36533660
Bind(&done);
36543661
}
@@ -4008,7 +4015,7 @@ void MacroAssembler::MoveObjectAndSlot(Register dst_object, Register dst_slot,
40084015
void MacroAssembler::RecordWrite(Register object, Operand offset,
40094016
Register value, LinkRegisterStatus lr_status,
40104017
SaveFPRegsMode fp_mode, SmiCheck smi_check,
4011-
SlotDescriptor slot) {
4018+
ReadOnlyCheck ro_check, SlotDescriptor slot) {
40124019
ASM_CODE_COMMENT(this);
40134020
ASM_LOCATION_IN_ASSEMBLER("MacroAssembler::RecordWrite");
40144021
DCHECK(!AreAliased(object, value));
@@ -4035,9 +4042,18 @@ void MacroAssembler::RecordWrite(Register object, Operand offset,
40354042
}
40364043

40374044
// First, check if a write barrier is even needed. The tests below
4038-
// catch stores of smis and stores into the young generation.
4045+
// catch stores of smisand read-only objects, as well as stores into the
4046+
// young generation.
40394047
Label done;
40404048

4049+
#if V8_STATIC_ROOTS_BOOL
4050+
if (ro_check == ReadOnlyCheck::kInline) {
4051+
// Quick check for Read-only and small Smi values.
4052+
static_assert(StaticReadOnlyRoot::kLastAllocatedRoot < kRegularPageSize);
4053+
JumpIfUnsignedLessThan(value, kRegularPageSize, &done);
4054+
}
4055+
#endif // V8_STATIC_ROOTS_BOOL
4056+
40414057
if (smi_check == SmiCheck::kInline) {
40424058
DCHECK_EQ(0, kSmiTag);
40434059
JumpIfSmi(value, &done);

src/codegen/arm64/macro-assembler-arm64.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,8 +1004,10 @@ class V8_EXPORT_PRIVATE MacroAssembler : public MacroAssemblerBase {
10041004
inline void JumpIfSmi(Register value, Label* smi_label,
10051005
Label* not_smi_label = nullptr);
10061006

1007+
inline void JumpIf(Condition cond, Register x, int32_t y, Label* dest);
10071008
inline void JumpIfEqual(Register x, int32_t y, Label* dest);
10081009
inline void JumpIfLessThan(Register x, int32_t y, Label* dest);
1010+
inline void JumpIfUnsignedLessThan(Register x, int32_t y, Label* dest);
10091011

10101012
void JumpIfMarking(Label* is_marking,
10111013
Label::Distance condition_met_distance = Label::kFar);
@@ -2257,6 +2259,7 @@ class V8_EXPORT_PRIVATE MacroAssembler : public MacroAssemblerBase {
22572259
void RecordWriteField(
22582260
Register object, int offset, Register value, LinkRegisterStatus lr_status,
22592261
SaveFPRegsMode save_fp, SmiCheck smi_check = SmiCheck::kInline,
2262+
ReadOnlyCheck ro_check = ReadOnlyCheck::kInline,
22602263
SlotDescriptor slot = SlotDescriptor::ForDirectPointerSlot());
22612264

22622265
// For a given |object| notify the garbage collector that the slot at |offset|
@@ -2265,6 +2268,7 @@ class V8_EXPORT_PRIVATE MacroAssembler : public MacroAssemblerBase {
22652268
Register object, Operand offset, Register value,
22662269
LinkRegisterStatus lr_status, SaveFPRegsMode save_fp,
22672270
SmiCheck smi_check = SmiCheck::kInline,
2271+
ReadOnlyCheck ro_check = ReadOnlyCheck::kInline,
22682272
SlotDescriptor slot = SlotDescriptor::ForDirectPointerSlot());
22692273

22702274
// ---------------------------------------------------------------------------

src/codegen/macro-assembler.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ enum class JumpMode {
3535
};
3636

3737
enum class SmiCheck { kOmit, kInline };
38+
enum class ReadOnlyCheck { kOmit, kInline };
3839

3940
enum class ComparisonMode {
4041
// The default compare mode will use a 32-bit comparison when pointer

src/codegen/x64/macro-assembler-x64.cc

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -428,13 +428,23 @@ void MacroAssembler::DecompressProtected(Register destination,
428428
void MacroAssembler::RecordWriteField(Register object, int offset,
429429
Register value, Register slot_address,
430430
SaveFPRegsMode save_fp,
431-
SmiCheck smi_check, SlotDescriptor slot) {
431+
SmiCheck smi_check,
432+
ReadOnlyCheck ro_check,
433+
SlotDescriptor slot) {
432434
ASM_CODE_COMMENT(this);
433435
DCHECK(!AreAliased(object, value, slot_address));
434436
// First, check if a write barrier is even needed. The tests below
435-
// catch stores of Smis.
437+
// catch stores of Smis and read-only objects.
436438
Label done;
437439

440+
#if V8_STATIC_ROOTS_BOOL
441+
if (ro_check == ReadOnlyCheck::kInline) {
442+
// Quick check for Read-only and small Smi values.
443+
static_assert(StaticReadOnlyRoot::kLastAllocatedRoot < kRegularPageSize);
444+
JumpIfUnsignedLessThan(value, kRegularPageSize, &done);
445+
}
446+
#endif // V8_STATIC_ROOTS_BOOL
447+
438448
// Skip barrier if writing a smi.
439449
if (smi_check == SmiCheck::kInline) {
440450
JumpIfSmi(value, &done);
@@ -454,7 +464,8 @@ void MacroAssembler::RecordWriteField(Register object, int offset,
454464
bind(&ok);
455465
}
456466

457-
RecordWrite(object, slot_address, value, save_fp, SmiCheck::kOmit, slot);
467+
RecordWrite(object, slot_address, value, save_fp, SmiCheck::kOmit,
468+
ReadOnlyCheck::kOmit, slot);
458469

459470
bind(&done);
460471

@@ -841,7 +852,8 @@ void MacroAssembler::CallTSANRelaxedLoadStub(Register address,
841852

842853
void MacroAssembler::RecordWrite(Register object, Register slot_address,
843854
Register value, SaveFPRegsMode fp_mode,
844-
SmiCheck smi_check, SlotDescriptor slot) {
855+
SmiCheck smi_check, ReadOnlyCheck ro_check,
856+
SlotDescriptor slot) {
845857
ASM_CODE_COMMENT(this);
846858
DCHECK(!AreAliased(object, slot_address, value));
847859
AssertNotSmi(object);
@@ -874,9 +886,18 @@ void MacroAssembler::RecordWrite(Register object, Register slot_address,
874886
}
875887

876888
// First, check if a write barrier is even needed. The tests below
877-
// catch stores of smis and stores into the young generation.
889+
// catch stores of smis and read-only objects, as well as stores into the
890+
// young generation.
878891
Label done;
879892

893+
#if V8_STATIC_ROOTS_BOOL
894+
if (ro_check == ReadOnlyCheck::kInline) {
895+
// Quick check for Read-only and small Smi values.
896+
static_assert(StaticReadOnlyRoot::kLastAllocatedRoot < kRegularPageSize);
897+
JumpIfUnsignedLessThan(value, kRegularPageSize, &done);
898+
}
899+
#endif // V8_STATIC_ROOTS_BOOL
900+
880901
if (smi_check == SmiCheck::kInline) {
881902
// Skip barrier if writing a smi.
882903
JumpIfSmi(value, &done);
@@ -1179,7 +1200,7 @@ void MacroAssembler::ReplaceClosureCodeWithOptimizedCode(
11791200

11801201
RecordWriteField(closure, JSFunction::kCodeOffset, value, slot_address,
11811202
SaveFPRegsMode::kIgnore, SmiCheck::kOmit,
1182-
SlotDescriptor::ForCodePointerSlot());
1203+
ReadOnlyCheck::kOmit, SlotDescriptor::ForCodePointerSlot());
11831204
#endif // V8_ENABLE_LEAPTIERING
11841205
}
11851206

src/codegen/x64/macro-assembler-x64.h

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -371,14 +371,21 @@ class V8_EXPORT_PRIVATE MacroAssembler
371371
// src is always unchanged.
372372
SmiIndex SmiToIndex(Register dst, Register src, int shift);
373373

374-
void JumpIfEqual(Register a, int32_t b, Label* dest) {
374+
void JumpIf(Condition cond, Register a, int32_t b, Label* dest) {
375375
cmpl(a, Immediate(b));
376-
j(equal, dest);
376+
j(cond, dest);
377+
}
378+
379+
void JumpIfEqual(Register a, int32_t b, Label* dest) {
380+
JumpIf(equal, a, b, dest);
377381
}
378382

379383
void JumpIfLessThan(Register a, int32_t b, Label* dest) {
380-
cmpl(a, Immediate(b));
381-
j(less, dest);
384+
JumpIf(less, a, b, dest);
385+
}
386+
387+
void JumpIfUnsignedLessThan(Register a, int32_t b, Label* dest) {
388+
JumpIf(below, a, b, dest);
382389
}
383390

384391
// Caution: if {reg} is a 32-bit negative int, it should be sign-extended to
@@ -876,6 +883,7 @@ class V8_EXPORT_PRIVATE MacroAssembler
876883
void RecordWriteField(
877884
Register object, int offset, Register value, Register slot_address,
878885
SaveFPRegsMode save_fp, SmiCheck smi_check = SmiCheck::kInline,
886+
ReadOnlyCheck ro_check = ReadOnlyCheck::kInline,
879887
SlotDescriptor slot = SlotDescriptor::ForDirectPointerSlot());
880888

881889
// For page containing |object| mark region covering |address|
@@ -886,6 +894,7 @@ class V8_EXPORT_PRIVATE MacroAssembler
886894
void RecordWrite(
887895
Register object, Register slot_address, Register value,
888896
SaveFPRegsMode save_fp, SmiCheck smi_check = SmiCheck::kInline,
897+
ReadOnlyCheck ro_check = ReadOnlyCheck::kInline,
889898
SlotDescriptor slot = SlotDescriptor::ForDirectPointerSlot());
890899

891900
// Allocates an EXIT/BUILTIN_EXIT/API_CALLBACK_EXIT frame with given number

0 commit comments

Comments
 (0)