MIPS: Improve write barriers in optimized code.
Port r21630 (a21ff10) Original commit message: Use a cheaper RecordWriteForMap() to update the write barrier for maps. And skip the value check in RecordWriteField() when we statically know that the value is in new space (and therefore has "pointers to here are interesting" flag set). BUG= R=plind44@gmail.com Review URL: https://codereview.chromium.org/315653002 Patch from Balazs Kilvady <kilvadyb@homejinni.com>. git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@21657 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
4aa31e0744
commit
bd99223cad
@ -4077,14 +4077,11 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
|
||||
if (instr->hydrogen()->NeedsWriteBarrierForMap()) {
|
||||
Register temp = ToRegister(instr->temp());
|
||||
// Update the write barrier for the map field.
|
||||
__ RecordWriteField(object,
|
||||
HeapObject::kMapOffset,
|
||||
scratch,
|
||||
temp,
|
||||
GetRAState(),
|
||||
kSaveFPRegs,
|
||||
OMIT_REMEMBERED_SET,
|
||||
OMIT_SMI_CHECK);
|
||||
__ RecordWriteForMap(object,
|
||||
scratch,
|
||||
temp,
|
||||
GetRAState(),
|
||||
kSaveFPRegs);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4102,7 +4099,8 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
|
||||
GetRAState(),
|
||||
kSaveFPRegs,
|
||||
EMIT_REMEMBERED_SET,
|
||||
instr->hydrogen()->SmiCheckForWriteBarrier());
|
||||
instr->hydrogen()->SmiCheckForWriteBarrier(),
|
||||
instr->hydrogen()->PointersToHereCheckForValue());
|
||||
}
|
||||
} else {
|
||||
__ lw(scratch, FieldMemOperand(object, JSObject::kPropertiesOffset));
|
||||
@ -4118,7 +4116,8 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
|
||||
GetRAState(),
|
||||
kSaveFPRegs,
|
||||
EMIT_REMEMBERED_SET,
|
||||
instr->hydrogen()->SmiCheckForWriteBarrier());
|
||||
instr->hydrogen()->SmiCheckForWriteBarrier(),
|
||||
instr->hydrogen()->PointersToHereCheckForValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4338,7 +4337,8 @@ void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
|
||||
GetRAState(),
|
||||
kSaveFPRegs,
|
||||
EMIT_REMEMBERED_SET,
|
||||
check_needed);
|
||||
check_needed,
|
||||
instr->hydrogen()->PointersToHereCheckForValue());
|
||||
}
|
||||
}
|
||||
|
||||
@ -4386,8 +4386,11 @@ void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
|
||||
__ li(new_map_reg, Operand(to_map));
|
||||
__ sw(new_map_reg, FieldMemOperand(object_reg, HeapObject::kMapOffset));
|
||||
// Write barrier.
|
||||
__ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg,
|
||||
scratch, GetRAState(), kDontSaveFPRegs);
|
||||
__ RecordWriteForMap(object_reg,
|
||||
new_map_reg,
|
||||
scratch,
|
||||
GetRAState(),
|
||||
kDontSaveFPRegs);
|
||||
} else {
|
||||
ASSERT(object_reg.is(a0));
|
||||
ASSERT(ToRegister(instr->context()).is(cp));
|
||||
|
@ -194,7 +194,8 @@ void MacroAssembler::RecordWriteField(
|
||||
RAStatus ra_status,
|
||||
SaveFPRegsMode save_fp,
|
||||
RememberedSetAction remembered_set_action,
|
||||
SmiCheck smi_check) {
|
||||
SmiCheck smi_check,
|
||||
PointersToHereCheck pointers_to_here_check_for_value) {
|
||||
ASSERT(!AreAliased(value, dst, t8, object));
|
||||
// First, check if a write barrier is even needed. The tests below
|
||||
// catch stores of Smis.
|
||||
@ -224,7 +225,8 @@ void MacroAssembler::RecordWriteField(
|
||||
ra_status,
|
||||
save_fp,
|
||||
remembered_set_action,
|
||||
OMIT_SMI_CHECK);
|
||||
OMIT_SMI_CHECK,
|
||||
pointers_to_here_check_for_value);
|
||||
|
||||
bind(&done);
|
||||
|
||||
@ -237,16 +239,93 @@ void MacroAssembler::RecordWriteField(
|
||||
}
|
||||
|
||||
|
||||
// Will clobber 4 registers: object, map, dst, ip. The
|
||||
// register 'object' contains a heap object pointer.
|
||||
void MacroAssembler::RecordWriteForMap(Register object,
|
||||
Register map,
|
||||
Register dst,
|
||||
RAStatus ra_status,
|
||||
SaveFPRegsMode fp_mode) {
|
||||
if (emit_debug_code()) {
|
||||
ASSERT(!dst.is(at));
|
||||
lw(dst, FieldMemOperand(map, HeapObject::kMapOffset));
|
||||
Check(eq,
|
||||
kWrongAddressOrValuePassedToRecordWrite,
|
||||
dst,
|
||||
Operand(isolate()->factory()->meta_map()));
|
||||
}
|
||||
|
||||
if (!FLAG_incremental_marking) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Count number of write barriers in generated code.
|
||||
isolate()->counters()->write_barriers_static()->Increment();
|
||||
// TODO(mstarzinger): Dynamic counter missing.
|
||||
|
||||
if (emit_debug_code()) {
|
||||
lw(at, FieldMemOperand(object, HeapObject::kMapOffset));
|
||||
Check(eq,
|
||||
kWrongAddressOrValuePassedToRecordWrite,
|
||||
map,
|
||||
Operand(at));
|
||||
}
|
||||
|
||||
Label done;
|
||||
|
||||
// A single check of the map's pages interesting flag suffices, since it is
|
||||
// only set during incremental collection, and then it's also guaranteed that
|
||||
// the from object's page's interesting flag is also set. This optimization
|
||||
// relies on the fact that maps can never be in new space.
|
||||
CheckPageFlag(map,
|
||||
map, // Used as scratch.
|
||||
MemoryChunk::kPointersToHereAreInterestingMask,
|
||||
eq,
|
||||
&done);
|
||||
|
||||
Addu(dst, object, Operand(HeapObject::kMapOffset - kHeapObjectTag));
|
||||
if (emit_debug_code()) {
|
||||
Label ok;
|
||||
And(at, dst, Operand((1 << kPointerSizeLog2) - 1));
|
||||
Branch(&ok, eq, at, Operand(zero_reg));
|
||||
stop("Unaligned cell in write barrier");
|
||||
bind(&ok);
|
||||
}
|
||||
|
||||
// Record the actual write.
|
||||
if (ra_status == kRAHasNotBeenSaved) {
|
||||
push(ra);
|
||||
}
|
||||
RecordWriteStub stub(isolate(), object, map, dst, OMIT_REMEMBERED_SET,
|
||||
fp_mode);
|
||||
CallStub(&stub);
|
||||
if (ra_status == kRAHasNotBeenSaved) {
|
||||
pop(ra);
|
||||
}
|
||||
|
||||
bind(&done);
|
||||
|
||||
// Clobber clobbered registers when running with the debug-code flag
|
||||
// turned on to provoke errors.
|
||||
if (emit_debug_code()) {
|
||||
li(dst, Operand(BitCast<int32_t>(kZapValue + 12)));
|
||||
li(map, Operand(BitCast<int32_t>(kZapValue + 16)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Will clobber 4 registers: object, address, scratch, ip. The
|
||||
// register 'object' contains a heap object pointer. The heap object
|
||||
// tag is shifted away.
|
||||
void MacroAssembler::RecordWrite(Register object,
|
||||
Register address,
|
||||
Register value,
|
||||
RAStatus ra_status,
|
||||
SaveFPRegsMode fp_mode,
|
||||
RememberedSetAction remembered_set_action,
|
||||
SmiCheck smi_check) {
|
||||
void MacroAssembler::RecordWrite(
|
||||
Register object,
|
||||
Register address,
|
||||
Register value,
|
||||
RAStatus ra_status,
|
||||
SaveFPRegsMode fp_mode,
|
||||
RememberedSetAction remembered_set_action,
|
||||
SmiCheck smi_check,
|
||||
PointersToHereCheck pointers_to_here_check_for_value) {
|
||||
ASSERT(!AreAliased(object, address, value, t8));
|
||||
ASSERT(!AreAliased(object, address, value, t9));
|
||||
|
||||
@ -256,6 +335,11 @@ void MacroAssembler::RecordWrite(Register object,
|
||||
eq, kWrongAddressOrValuePassedToRecordWrite, at, Operand(value));
|
||||
}
|
||||
|
||||
if (remembered_set_action == OMIT_REMEMBERED_SET &&
|
||||
!FLAG_incremental_marking) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Count number of write barriers in generated code.
|
||||
isolate()->counters()->write_barriers_static()->Increment();
|
||||
// TODO(mstarzinger): Dynamic counter missing.
|
||||
@ -269,11 +353,13 @@ void MacroAssembler::RecordWrite(Register object,
|
||||
JumpIfSmi(value, &done);
|
||||
}
|
||||
|
||||
CheckPageFlag(value,
|
||||
value, // Used as scratch.
|
||||
MemoryChunk::kPointersToHereAreInterestingMask,
|
||||
eq,
|
||||
&done);
|
||||
if (pointers_to_here_check_for_value != kPointersToHereAreAlwaysInteresting) {
|
||||
CheckPageFlag(value,
|
||||
value, // Used as scratch.
|
||||
MemoryChunk::kPointersToHereAreInterestingMask,
|
||||
eq,
|
||||
&done);
|
||||
}
|
||||
CheckPageFlag(object,
|
||||
value, // Used as scratch.
|
||||
MemoryChunk::kPointersFromHereAreInterestingMask,
|
||||
|
@ -71,6 +71,10 @@ enum LiFlags {
|
||||
|
||||
enum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET };
|
||||
enum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK };
|
||||
enum PointersToHereCheck {
|
||||
kPointersToHereMaybeInteresting,
|
||||
kPointersToHereAreAlwaysInteresting
|
||||
};
|
||||
enum RAStatus { kRAHasNotBeenSaved, kRAHasBeenSaved };
|
||||
|
||||
Register GetRegisterThatIsNotOneOf(Register reg1,
|
||||
@ -365,7 +369,9 @@ class MacroAssembler: public Assembler {
|
||||
RAStatus ra_status,
|
||||
SaveFPRegsMode save_fp,
|
||||
RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
|
||||
SmiCheck smi_check = INLINE_SMI_CHECK);
|
||||
SmiCheck smi_check = INLINE_SMI_CHECK,
|
||||
PointersToHereCheck pointers_to_here_check_for_value =
|
||||
kPointersToHereMaybeInteresting);
|
||||
|
||||
// As above, but the offset has the tag presubtracted. For use with
|
||||
// MemOperand(reg, off).
|
||||
@ -377,7 +383,9 @@ class MacroAssembler: public Assembler {
|
||||
RAStatus ra_status,
|
||||
SaveFPRegsMode save_fp,
|
||||
RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
|
||||
SmiCheck smi_check = INLINE_SMI_CHECK) {
|
||||
SmiCheck smi_check = INLINE_SMI_CHECK,
|
||||
PointersToHereCheck pointers_to_here_check_for_value =
|
||||
kPointersToHereMaybeInteresting) {
|
||||
RecordWriteField(context,
|
||||
offset + kHeapObjectTag,
|
||||
value,
|
||||
@ -385,9 +393,17 @@ class MacroAssembler: public Assembler {
|
||||
ra_status,
|
||||
save_fp,
|
||||
remembered_set_action,
|
||||
smi_check);
|
||||
smi_check,
|
||||
pointers_to_here_check_for_value);
|
||||
}
|
||||
|
||||
void RecordWriteForMap(
|
||||
Register object,
|
||||
Register map,
|
||||
Register dst,
|
||||
RAStatus ra_status,
|
||||
SaveFPRegsMode save_fp);
|
||||
|
||||
// For a given |object| notify the garbage collector that the slot |address|
|
||||
// has been written. |value| is the object being stored. The value and
|
||||
// address registers are clobbered by the operation.
|
||||
@ -398,7 +414,9 @@ class MacroAssembler: public Assembler {
|
||||
RAStatus ra_status,
|
||||
SaveFPRegsMode save_fp,
|
||||
RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
|
||||
SmiCheck smi_check = INLINE_SMI_CHECK);
|
||||
SmiCheck smi_check = INLINE_SMI_CHECK,
|
||||
PointersToHereCheck pointers_to_here_check_for_value =
|
||||
kPointersToHereMaybeInteresting);
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user