| 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,
|
|
|