Index: src/arm/macro-assembler-arm.cc |
diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc |
index 7d590c29bc4a638d6fb49e0df4a9243faff84f3f..a8d4b7ccd458d2e26ec54ee5c40ff3f1a51d0d20 100644 |
--- a/src/arm/macro-assembler-arm.cc |
+++ b/src/arm/macro-assembler-arm.cc |
@@ -453,7 +453,8 @@ void MacroAssembler::RecordWriteField( |
LinkRegisterStatus lr_status, |
SaveFPRegsMode save_fp, |
RememberedSetAction remembered_set_action, |
- SmiCheck smi_check) { |
+ SmiCheck smi_check, |
+ PointersToHereCheck pointers_to_here_check_for_value) { |
// First, check if a write barrier is even needed. The tests below |
// catch stores of Smis. |
Label done; |
@@ -482,7 +483,8 @@ void MacroAssembler::RecordWriteField( |
lr_status, |
save_fp, |
remembered_set_action, |
- OMIT_SMI_CHECK); |
+ OMIT_SMI_CHECK, |
+ pointers_to_here_check_for_value); |
bind(&done); |
@@ -495,16 +497,88 @@ 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, |
+ LinkRegisterStatus lr_status, |
+ SaveFPRegsMode fp_mode) { |
+ if (emit_debug_code()) { |
+ ldr(dst, FieldMemOperand(map, HeapObject::kMapOffset)); |
+ cmp(dst, Operand(isolate()->factory()->meta_map())); |
+ Check(eq, kWrongAddressOrValuePassedToRecordWrite); |
+ } |
+ |
+ 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()) { |
+ ldr(ip, FieldMemOperand(object, HeapObject::kMapOffset)); |
+ cmp(ip, map); |
+ Check(eq, kWrongAddressOrValuePassedToRecordWrite); |
+ } |
+ |
+ 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); |
+ |
+ add(dst, object, Operand(HeapObject::kMapOffset - kHeapObjectTag)); |
+ if (emit_debug_code()) { |
+ Label ok; |
+ tst(dst, Operand((1 << kPointerSizeLog2) - 1)); |
+ b(eq, &ok); |
+ stop("Unaligned cell in write barrier"); |
+ bind(&ok); |
+ } |
+ |
+ // Record the actual write. |
+ if (lr_status == kLRHasNotBeenSaved) { |
+ push(lr); |
+ } |
+ RecordWriteStub stub(isolate(), object, map, dst, OMIT_REMEMBERED_SET, |
+ fp_mode); |
+ CallStub(&stub); |
+ if (lr_status == kLRHasNotBeenSaved) { |
+ pop(lr); |
+ } |
+ |
+ bind(&done); |
+ |
+ // Clobber clobbered registers when running with the debug-code flag |
+ // turned on to provoke errors. |
+ if (emit_debug_code()) { |
+ mov(dst, Operand(BitCast<int32_t>(kZapValue + 12))); |
+ mov(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, |
- LinkRegisterStatus lr_status, |
- SaveFPRegsMode fp_mode, |
- RememberedSetAction remembered_set_action, |
- SmiCheck smi_check) { |
+void MacroAssembler::RecordWrite( |
+ Register object, |
+ Register address, |
+ Register value, |
+ LinkRegisterStatus lr_status, |
+ SaveFPRegsMode fp_mode, |
+ RememberedSetAction remembered_set_action, |
+ SmiCheck smi_check, |
+ PointersToHereCheck pointers_to_here_check_for_value) { |
ASSERT(!object.is(value)); |
if (emit_debug_code()) { |
ldr(ip, MemOperand(address)); |
@@ -512,6 +586,11 @@ void MacroAssembler::RecordWrite(Register object, |
Check(eq, kWrongAddressOrValuePassedToRecordWrite); |
} |
+ 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. |
@@ -524,11 +603,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, |