Index: src/ia32/macro-assembler-ia32.cc |
diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc |
index 1b614867cd4a1bfa29efda6623fd41cc5bece440..e4d3fb7c3716bfa7398c7784cd3e487ddb921634 100644 |
--- a/src/ia32/macro-assembler-ia32.cc |
+++ b/src/ia32/macro-assembler-ia32.cc |
@@ -237,6 +237,70 @@ void MacroAssembler::RecordWriteField( |
} |
+void MacroAssembler::RecordWriteForMap( |
+ Register object, |
+ Handle<Map> map, |
+ Register scratch1, |
+ Register scratch2, |
+ SaveFPRegsMode save_fp) { |
+ // First, check if a write barrier is even needed. The tests below |
+ // catch stores of Smis. |
+ Label done; |
+ |
+ Register address = scratch1; |
+ Register value = scratch2; |
+ if (emit_debug_code()) { |
+ Label ok; |
+ lea(address, FieldOperand(object, HeapObject::kMapOffset)); |
+ test_b(address, (1 << kPointerSizeLog2) - 1); |
+ j(zero, &ok, Label::kNear); |
+ int3(); |
+ bind(&ok); |
+ } |
+ |
+ ASSERT(!object.is(value)); |
+ ASSERT(!object.is(address)); |
+ ASSERT(!value.is(address)); |
+ if (emit_debug_code()) { |
+ AbortIfSmi(object); |
+ } |
+ |
+ if (!FLAG_incremental_marking) { |
+ return; |
+ } |
+ |
+ // 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. |
+ ASSERT(!isolate()->heap()->InNewSpace(*map)); |
+ CheckPageFlagForMap(map, |
+ MemoryChunk::kPointersToHereAreInterestingMask, |
+ zero, |
+ &done, |
+ Label::kNear); |
+ |
+ // Delay the initialization of |address| and |value| for the stub until it's |
+ // known that the will be needed. Up until this point their value are not |
+ // needed since they are embedded in the operands of instructions that need |
+ // them. |
+ lea(address, FieldOperand(object, HeapObject::kMapOffset)); |
+ mov(value, Immediate(map)); |
+ RecordWriteStub stub(object, value, address, OMIT_REMEMBERED_SET, save_fp); |
+ CallStub(&stub); |
+ |
+ bind(&done); |
+ |
+ // Clobber clobbered input registers when running with the debug-code flag |
+ // turned on to provoke errors. |
+ if (emit_debug_code()) { |
+ mov(value, Immediate(BitCast<int32_t>(kZapValue))); |
+ mov(scratch1, Immediate(BitCast<int32_t>(kZapValue))); |
+ mov(scratch2, Immediate(BitCast<int32_t>(kZapValue))); |
+ } |
+} |
+ |
+ |
void MacroAssembler::RecordWrite(Register object, |
Register address, |
Register value, |
@@ -2618,6 +2682,28 @@ void MacroAssembler::CheckPageFlag( |
} |
+void MacroAssembler::CheckPageFlagForMap( |
+ Handle<Map> map, |
+ int mask, |
+ Condition cc, |
+ Label* condition_met, |
+ Label::Distance condition_met_distance) { |
+ ASSERT(cc == zero || cc == not_zero); |
+ Page* page = Page::FromAddress(map->address()); |
+ ExternalReference reference(ExternalReference::page_flags(page)); |
+ // The inlined static address check of the page's flags relies |
+ // on maps never being compacted. |
+ ASSERT(!isolate()->heap()->mark_compact_collector()-> |
+ IsOnEvacuationCandidate(*map)); |
+ if (mask < (1 << kBitsPerByte)) { |
+ test_b(Operand::StaticVariable(reference), static_cast<uint8_t>(mask)); |
+ } else { |
+ test(Operand::StaticVariable(reference), Immediate(mask)); |
+ } |
+ j(cc, condition_met, condition_met_distance); |
+} |
+ |
+ |
void MacroAssembler::JumpIfBlack(Register object, |
Register scratch0, |
Register scratch1, |