Chromium Code Reviews| Index: src/arm/macro-assembler-arm.cc |
| =================================================================== |
| --- src/arm/macro-assembler-arm.cc (revision 8184) |
| +++ src/arm/macro-assembler-arm.cc (working copy) |
| @@ -482,6 +482,7 @@ |
| int offset, |
| Register value, |
| Register dst, |
| + LinkRegisterStatus lr_status, |
| SaveFPRegsMode save_fp, |
| RememberedSetAction remembered_set_action, |
| SmiCheck smi_check) { |
| @@ -506,8 +507,13 @@ |
| bind(&ok); |
| } |
| - RecordWrite( |
| - object, dst, value, save_fp, remembered_set_action, OMIT_SMI_CHECK); |
| + RecordWrite(object, |
| + dst, |
| + value, |
| + lr_status, |
| + save_fp, |
| + remembered_set_action, |
| + OMIT_SMI_CHECK); |
| bind(&done); |
| @@ -525,38 +531,60 @@ |
| // tag is shifted away. |
| void MacroAssembler::RecordWrite(Register object, |
| Register address, |
| - Register scratch, |
| + Register value, |
| + LinkRegisterStatus lr_status, |
| SaveFPRegsMode fp_mode, |
| RememberedSetAction remembered_set_action, |
| SmiCheck smi_check) { |
| // The compiled code assumes that record write doesn't change the |
| // context register, so we check that none of the clobbered |
| // registers are cp. |
| - ASSERT(!address.is(cp) && !scratch.is(cp)); |
| + ASSERT(!address.is(cp) && !value.is(cp)); |
| Label done; |
| - // First, test that the object is not in the new space. We cannot set |
| - // region marks for new space pages. |
| - InNewSpace(object, scratch, eq, &done); |
| + if (smi_check == INLINE_SMI_CHECK) { |
| + ASSERT_EQ(0, kSmiTag); |
| + tst(value, Operand(kSmiTagMask)); |
| + b(eq, &done); |
| + } |
| + CheckPageFlag(value, |
| + value, // Used as scratch. |
| + MemoryChunk::POINTERS_TO_HERE_ARE_INTERESTING, |
| + eq, |
| + &done); |
| + CheckPageFlag(object, |
| + value, // Used as scratch. |
| + MemoryChunk::POINTERS_FROM_HERE_ARE_INTERESTING, |
| + eq, |
| + &done); |
| + |
| // Record the actual write. |
| - RememberedSetHelper(address, scratch, fp_mode); |
| + if (lr_status == kLRHasNotBeenSaved) { |
| + push(lr); |
| + } |
| + RecordWriteStub stub(object, value, address, remembered_set_action, fp_mode); |
| + CallStub(&stub); |
| + if (lr_status == kLRHasNotBeenSaved) { |
| + pop(lr); |
| + } |
| bind(&done); |
| - // Clobber all input registers when running with the debug-code flag |
| + // Clobber clobbered registers when running with the debug-code flag |
| // turned on to provoke errors. |
| if (emit_debug_code()) { |
| mov(address, Operand(BitCast<int32_t>(kZapValue + 12))); |
| - mov(scratch, Operand(BitCast<int32_t>(kZapValue + 16))); |
| + mov(value, Operand(BitCast<int32_t>(kZapValue + 16))); |
| } |
| } |
| void MacroAssembler::RememberedSetHelper(Register address, |
| Register scratch, |
| - SaveFPRegsMode fp_mode) { |
| + SaveFPRegsMode fp_mode, |
| + RememberedSetFinalAction and_then) { |
| Label done; |
| // Load store buffer top. |
| ExternalReference store_buffer = |
| @@ -570,13 +598,21 @@ |
| // Call stub on end of buffer. |
| // Check for end of buffer. |
| tst(scratch, Operand(StoreBuffer::kStoreBufferOverflowBit)); |
| - b(eq, &done); |
| + if (and_then == kFallThroughAtEnd) { |
| + b(eq, &done); |
| + } else { |
| + ASSERT(and_then == kReturnAtEnd); |
| + Ret(ne); |
| + } |
| push(lr); |
| StoreBufferOverflowStub store_buffer_overflow = |
| StoreBufferOverflowStub(fp_mode); |
| CallStub(&store_buffer_overflow); |
| pop(lr); |
| bind(&done); |
| + if (and_then == kReturnAtEnd) { |
| + Ret(); |
| + } |
| } |
| @@ -3092,6 +3128,60 @@ |
| } |
| +void MacroAssembler::IsBlack(Register object, |
| + Register scratch0, |
| + Register scratch1, |
| + Label* is_black) { |
| + HasColour(object, scratch0, scratch1, |
| + is_black, |
| + 1, 0); // kBlackBitPattern. |
| + ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0); |
| +} |
| + |
| + |
| +void MacroAssembler::HasColour(Register object, |
|
Lasse Reichstein
2011/06/07 08:48:37
I think we generally use the Bowdlerized US Englis
Erik Corry
2011/06/08 10:31:29
Auch! That hert!
|
| + Register bitmap_scratch, |
| + Register mask_scratch, |
| + Label* has_colour, |
| + int first_bit, |
| + int second_bit) { |
| + ASSERT(!Aliasing(object, bitmap_scratch, mask_scratch, no_reg)); |
| + |
| + MarkBits(object, bitmap_scratch, mask_scratch); |
|
Lasse Reichstein
2011/06/07 08:48:37
Could MarkBits be named something that sounds less
Erik Corry
2011/06/08 10:31:29
GetMarkBits
|
| + |
| + Label other_colour, word_boundary; |
| + ldr(ip, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); |
| + tst(ip, Operand(mask_scratch)); |
| + b(first_bit == 1 ? eq : ne, &other_colour); |
| + // Shift left 1 by adding. |
| + add(mask_scratch, mask_scratch, Operand(mask_scratch), SetCC); |
| + b(eq, &word_boundary); |
|
Lasse Reichstein
2011/06/07 08:48:37
Should this be optimized for speed or size?
If spe
Erik Corry
2011/06/08 10:31:29
I think there's room for experimentation here, but
|
| + tst(ip, Operand(mask_scratch)); |
| + b(second_bit == 1 ? ne : eq, has_colour); |
| + jmp(&other_colour); |
| + |
| + bind(&word_boundary); |
| + ldr(ip, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize + kPointerSize)); |
| + tst(ip, Operand(1)); |
| + b(second_bit == 1 ? ne : eq, has_colour); |
| + bind(&other_colour); |
| +} |
| + |
| + |
| +void MacroAssembler::MarkBits(Register addr_reg, |
| + Register bitmap_reg, |
| + Register mask_reg) { |
| + ASSERT(!Aliasing(addr_reg, bitmap_reg, mask_reg, no_reg)); |
| + and_(bitmap_reg, addr_reg, Operand(~Page::kPageAlignmentMask)); |
| + Ubfx(mask_reg, addr_reg, kPointerSizeLog2, Bitmap::kBitsPerCellLog2); |
| + const int kLowBits = kPointerSizeLog2 + Bitmap::kBitsPerCellLog2; |
| + Ubfx(ip, addr_reg, kLowBits, kPageSizeBits - kLowBits); |
| + add(bitmap_reg, bitmap_reg, Operand(ip, LSL, kPointerSizeLog2)); |
| + mov(ip, Operand(1)); |
| + mov(mask_reg, Operand(ip, LSL, mask_reg)); |
| +} |
| + |
| + |
| void MacroAssembler::ClampUint8(Register output_reg, Register input_reg) { |
| Usat(output_reg, 8, Operand(input_reg)); |
| } |
| @@ -3141,6 +3231,17 @@ |
| } |
| +bool Aliasing(Register r1, Register r2, Register r3, Register r4) { |
| + if (r1.is(r2)) return true; |
| + if (r1.is(r3)) return true; |
| + if (r1.is(r4)) return true; |
| + if (r2.is(r3)) return true; |
| + if (r2.is(r4)) return true; |
| + if (r3.is(r4)) return true; |
| + return false; |
| +} |
| + |
| + |
| CodePatcher::CodePatcher(byte* address, int instructions) |
| : address_(address), |
| instructions_(instructions), |