Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(208)

Unified Diff: src/x64/macro-assembler-x64.cc

Issue 160453: X64: Reenabled RSet. (Closed)
Patch Set: Created 11 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« src/x64/assembler-x64.h ('K') | « src/x64/ic-x64.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/x64/macro-assembler-x64.cc
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc
index f58e1cdf9b6a95f702ace91a61db154a0ddcc061..93134362ddc6915ec472ab82382f5c2d39a507de 100644
--- a/src/x64/macro-assembler-x64.cc
+++ b/src/x64/macro-assembler-x64.cc
@@ -31,6 +31,7 @@
#include "codegen-inl.h"
#include "assembler-x64.h"
#include "macro-assembler-x64.h"
+#include "serialize.h"
#include "debug.h"
namespace v8 {
@@ -45,11 +46,190 @@ MacroAssembler::MacroAssembler(void* buffer, int size)
}
-// TODO(x64): For now, the write barrier is disabled on x64 and we
-// therefore generate no code. This should be fixed when the write
-// barrier is enabled.
-void MacroAssembler::RecordWrite(Register object, int offset,
- Register value, Register scratch) {
+
+static void RecordWriteHelper(MacroAssembler* masm,
+ Register object,
+ Register addr,
+ Register scratch) {
+ Label fast;
+
+ // Compute the page address from the heap object pointer, leave it
+ // in 'object'.
+ ASSERT(is_int32(~Page::kPageAlignmentMask));
+ masm->and_(object,
+ Immediate(static_cast<int32_t>(~Page::kPageAlignmentMask)));
+
+ // Compute the bit addr in the remembered set, leave it in "addr".
+ masm->subq(addr, object);
+ masm->shr(addr, Immediate(kPointerSizeLog2));
+
+ // If the bit offset lies beyond the normal remembered set range, it is in
+ // the extra remembered set area of a large object.
+ masm->cmpq(addr, Immediate(Page::kPageSize / kPointerSize));
+ masm->j(less, &fast);
+
+ // Adjust 'addr' to be relative to the start of the extra remembered set
+ // and the page address in 'object' to be the address of the extra
+ // remembered set.
+ masm->subq(addr, Immediate(Page::kPageSize / kPointerSize));
+ // Load the array length into 'scratch'.
+ masm->movl(scratch,
+ Operand(object,
+ Page::kObjectStartOffset + FixedArray::kLengthOffset));
+ // Extra remembered set starts right after FixedArray.
+ // Add the page header, array header, and array body size
+ // (length * pointer size) to the page address to find the extra remembered
+ // set start.
+ masm->lea(object,
+ Operand(object, scratch, times_pointer_size,
+ Page::kObjectStartOffset + FixedArray::kHeaderSize));
+
+ // NOTE: For now, we use the bit-test-and-set (bts) x86 instruction
+ // to limit code size. We should probably evaluate this decision by
+ // measuring the performance of an equivalent implementation using
+ // "simpler" instructions
+ masm->bind(&fast);
+ masm->bts(Operand(object, Page::kRSetOffset), addr);
+}
+
+
+class RecordWriteStub : public CodeStub {
+ public:
+ RecordWriteStub(Register object, Register addr, Register scratch)
+ : object_(object), addr_(addr), scratch_(scratch) { }
+
+ void Generate(MacroAssembler* masm);
+
+ private:
+ Register object_;
+ Register addr_;
+ Register scratch_;
+
+#ifdef DEBUG
+ void Print() {
+ PrintF("RecordWriteStub (object reg %d), (addr reg %d), (scratch reg %d)\n",
+ object_.code(), addr_.code(), scratch_.code());
+ }
+#endif
+
+ // Minor key encoding in 12 bits of three registers (object, address and
+ // scratch) OOOOAAAASSSS.
+ class ScratchBits: public BitField<uint32_t, 0, 4> {};
+ class AddressBits: public BitField<uint32_t, 4, 4> {};
+ class ObjectBits: public BitField<uint32_t, 8, 4> {};
+
+ Major MajorKey() { return RecordWrite; }
+
+ int MinorKey() {
+ // Encode the registers.
+ return ObjectBits::encode(object_.code()) |
+ AddressBits::encode(addr_.code()) |
+ ScratchBits::encode(scratch_.code());
+ }
+};
+
+
+void RecordWriteStub::Generate(MacroAssembler* masm) {
+ RecordWriteHelper(masm, object_, addr_, scratch_);
+ masm->ret(0);
+}
+
+
+// Set the remembered set bit for [object+offset].
+// object is the object being stored into, value is the object being stored.
+// If offset is zero, then the scratch register contains the array index into
+// the elements array represented as a Smi.
+// All registers are clobbered by the operation.
+void MacroAssembler::RecordWrite(Register object,
+ int offset,
+ Register value,
+ Register scratch) {
+ // First, check if a remembered set write is even needed. The tests below
+ // catch stores of Smis and stores into young gen (which does not have space
+ // for the remembered set bits.
+ Label done;
+
+ // This optimization cannot survive serialization and deserialization,
+ // so we disable as long as serialization can take place.
+ intptr_t new_space_start =
+ reinterpret_cast<intptr_t>(
+ ExternalReference::new_space_start().address());
+ if (Serializer::enabled() || new_space_start < 0) {
+ // Cannot do smart bit-twiddling. Need to do two consecutive checks.
+ // Check for Smi first.
+ testl(value, Immediate(kSmiTagMask));
+ j(zero, &done);
William Hesse 2009/08/03 09:03:28 Remove this smi test - we think it isn't worth it.
Lasse Reichstein 2009/08/03 10:45:45 Done.
+ // Test that the object address is not in the new space. We cannot
+ // set remembered set bits in the new space.
+ movq(value, object);
+ ASSERT(is_int32(static_cast<int64_t>(Heap::NewSpaceMask())));
+ and_(value, Immediate(static_cast<int32_t>(Heap::NewSpaceMask())));
+ movq(kScratchRegister, ExternalReference::new_space_start());
+ cmpq(value, kScratchRegister);
+ j(equal, &done);
+ } else {
William Hesse 2009/08/03 09:03:28 This optimization is unsafe if object can be in th
Lasse Reichstein 2009/08/03 10:45:45 Done.
+ // move the value SmiTag into the sign bit
+ ASSERT(kSmiTagSize == 1);
+ ASSERT(kSmiTag == 0);
+ shl(value, Immediate(63));
+
+ // remove the uninteresting bits inside the page
+ movq(kScratchRegister, object);
+ ASSERT(is_int32(static_cast<int64_t>(Heap::NewSpaceMask())));
+ and_(kScratchRegister,
+ Immediate(static_cast<int32_t>(Heap::NewSpaceMask())));
+ // combine the object with value SmiTag
+ or_(value, kScratchRegister);
+ // xor has two effects:
+ // - if the value was a smi, then the result will be negative
+ // - if the object is pointing into new space area the page bits will
+ // all be zero.
+ movq(kScratchRegister, new_space_start | (static_cast<int64_t>(1) << 63),
+ RelocInfo::NONE);
+ xor_(value, kScratchRegister);
+ // Check for both conditions in one branch
+ j(less_equal, &done); // Jump if either zero or sign flag set.
+ }
+
+ if ((offset > 0) && (offset < Page::kMaxHeapObjectSize)) {
+ // Compute the bit offset in the remembered set, leave it in 'value'.
+ movq(value, object);
+ ASSERT(is_uint32(Page::kPageAlignmentMask));
+ and_(value, Immediate(static_cast<uint32_t>(Page::kPageAlignmentMask)));
+ addq(value, Immediate(offset));
+ shr(value, Immediate(kObjectAlignmentBits));
+
+ // Compute the page address from the heap object pointer, leave it in
+ // 'object' (immediate value is sign extended).
+ and_(object, Immediate(~Page::kPageAlignmentMask));
+
+ // NOTE: For now, we use the bit-test-and-set (bts) x86 instruction
+ // to limit code size. We should probably evaluate this decision by
+ // measuring the performance of an equivalent implementation using
+ // "simpler" instructions
+ bts(Operand(object, Page::kRSetOffset), value);
+ } else {
+ Register dst = scratch;
+ if (offset != 0) {
+ lea(dst, Operand(object, offset));
+ } else {
+ // array access: calculate the destination address in the same manner as
+ // KeyedStoreIC::GenerateGeneric. Multiply a smi by 4 to get an offset
+ // into an array of words.
+ lea(dst, Operand(object, dst, times_half_pointer_size,
+ FixedArray::kHeaderSize - kHeapObjectTag));
+ }
+ // If we are already generating a shared stub, not inlining the
+ // record write code isn't going to save us any memory.
+ if (generating_stub()) {
+ RecordWriteHelper(this, object, dst, value);
+ } else {
+ RecordWriteStub stub(object, dst, value);
+ CallStub(&stub);
+ }
+ }
+
+ bind(&done);
}
« src/x64/assembler-x64.h ('K') | « src/x64/ic-x64.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698