Commit 30fa78f1 authored by lrn@chromium.org's avatar lrn@chromium.org

Fix bug in X64 RSet code. Optimize IA32 version.

Review URL: http://codereview.chromium.org/162001


git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2626 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent ed09a3bf
...@@ -54,41 +54,47 @@ static void RecordWriteHelper(MacroAssembler* masm, ...@@ -54,41 +54,47 @@ static void RecordWriteHelper(MacroAssembler* masm,
Register scratch) { Register scratch) {
Label fast; Label fast;
// Compute the page address from the heap object pointer, leave it // Compute the page start address from the heap object pointer, and reuse
// in 'object'. // the 'object' register for it.
masm->and_(object, ~Page::kPageAlignmentMask); masm->and_(object, ~Page::kPageAlignmentMask);
Register page_start = object;
// Compute the bit addr in the remembered set, leave it in "addr". // Compute the bit addr in the remembered set/index of the pointer in the
masm->sub(addr, Operand(object)); // page. Reuse 'addr' as pointer_offset.
masm->sub(addr, Operand(page_start));
masm->shr(addr, kObjectAlignmentBits); masm->shr(addr, kObjectAlignmentBits);
Register pointer_offset = addr;
// If the bit offset lies beyond the normal remembered set range, it is in // If the bit offset lies beyond the normal remembered set range, it is in
// the extra remembered set area of a large object. // the extra remembered set area of a large object.
masm->cmp(addr, Page::kPageSize / kPointerSize); masm->cmp(pointer_offset, Page::kPageSize / kPointerSize);
masm->j(less, &fast); masm->j(less, &fast);
// Adjust 'addr' to be relative to the start of the extra remembered set // Adjust 'page_start' so that addressing using 'pointer_offset' hits the
// and the page address in 'object' to be the address of the extra // extra remembered set after the large object.
// remembered set.
masm->sub(Operand(addr), Immediate(Page::kPageSize / kPointerSize)); // Find the length of the large object (FixedArray).
// Load the array length into 'scratch' and multiply by four to get the masm->mov(scratch, Operand(page_start, Page::kObjectStartOffset
// size in bytes of the elements. + FixedArray::kLengthOffset));
masm->mov(scratch, Operand(object, Page::kObjectStartOffset Register array_length = scratch;
+ FixedArray::kLengthOffset));
masm->shl(scratch, kObjectAlignmentBits); // Extra remembered set starts right after the large object (a FixedArray), at
// Add the page header, array header, and array body size to the page // page_start + kObjectStartOffset + objectSize
// address. // where objectSize is FixedArray::kHeaderSize + kPointerSize * array_length.
masm->add(Operand(object), Immediate(Page::kObjectStartOffset // Add the delta between the end of the normal RSet and the start of the
+ FixedArray::kHeaderSize)); // extra RSet to 'object', so that addressing the bit using 'pointer_offset'
masm->add(object, Operand(scratch)); // hits the extra RSet words.
masm->lea(page_start,
Operand(page_start, array_length, times_pointer_size,
Page::kObjectStartOffset + FixedArray::kHeaderSize
- Page::kRSetEndOffset));
// NOTE: For now, we use the bit-test-and-set (bts) x86 instruction // NOTE: For now, we use the bit-test-and-set (bts) x86 instruction
// to limit code size. We should probably evaluate this decision by // to limit code size. We should probably evaluate this decision by
// measuring the performance of an equivalent implementation using // measuring the performance of an equivalent implementation using
// "simpler" instructions // "simpler" instructions
masm->bind(&fast); masm->bind(&fast);
masm->bts(Operand(object, 0), addr); masm->bts(Operand(page_start, Page::kRSetOffset), pointer_offset);
} }
......
...@@ -127,20 +127,19 @@ Address Page::ComputeRSetBitPosition(Address address, int offset, ...@@ -127,20 +127,19 @@ Address Page::ComputeRSetBitPosition(Address address, int offset,
if (rset_address >= page->RSetEnd()) { if (rset_address >= page->RSetEnd()) {
// We have a large object page, and the remembered set address is actually // We have a large object page, and the remembered set address is actually
// past the end of the object. The address of the remembered set in this // past the end of the object.
// case is the extra remembered set start address at the address of the
// end of the object: // The first part of the remembered set is still located at the start of
// the page, but anything after kRSetEndOffset must be relocated to after
// the large object, i.e. after
// (page->ObjectAreaStart() + object size) // (page->ObjectAreaStart() + object size)
// plus the offset of the computed remembered set address from the start // We do that by adding the difference between the normal RSet's end and
// of the object: // the object's end.
// (rset_address - page->ObjectAreaStart()).
// Ie, we can just add the object size.
// In the X64 architecture, the remembered set ends before the object start,
// so we need to add an additional offset, from rset end to object start
ASSERT(HeapObject::FromAddress(address)->IsFixedArray()); ASSERT(HeapObject::FromAddress(address)->IsFixedArray());
rset_address += kObjectStartOffset - kRSetEndOffset + int fixedarray_length =
FixedArray::SizeFor(Memory::int_at(page->ObjectAreaStart() FixedArray::SizeFor(Memory::int_at(page->ObjectAreaStart()
+ Array::kLengthOffset)); + Array::kLengthOffset));
rset_address += kObjectStartOffset - kRSetEndOffset + fixedarray_length;
} }
return rset_address; return rset_address;
} }
......
...@@ -53,43 +53,50 @@ static void RecordWriteHelper(MacroAssembler* masm, ...@@ -53,43 +53,50 @@ static void RecordWriteHelper(MacroAssembler* masm,
Register scratch) { Register scratch) {
Label fast; Label fast;
// Compute the page address from the heap object pointer, leave it // Compute the page start address from the heap object pointer, and reuse
// in 'object'. // the 'object' register for it.
ASSERT(is_int32(~Page::kPageAlignmentMask)); ASSERT(is_int32(~Page::kPageAlignmentMask));
masm->and_(object, masm->and_(object,
Immediate(static_cast<int32_t>(~Page::kPageAlignmentMask))); Immediate(static_cast<int32_t>(~Page::kPageAlignmentMask)));
Register page_start = object;
// Compute the bit addr in the remembered set, leave it in "addr". // Compute the bit addr in the remembered set/index of the pointer in the
masm->subq(addr, object); // page. Reuse 'addr' as pointer_offset.
masm->subq(addr, page_start);
masm->shr(addr, Immediate(kPointerSizeLog2)); masm->shr(addr, Immediate(kPointerSizeLog2));
Register pointer_offset = addr;
// If the bit offset lies beyond the normal remembered set range, it is in // If the bit offset lies beyond the normal remembered set range, it is in
// the extra remembered set area of a large object. // the extra remembered set area of a large object.
masm->cmpq(addr, Immediate(Page::kPageSize / kPointerSize)); masm->cmpq(pointer_offset, Immediate(Page::kPageSize / kPointerSize));
masm->j(less, &fast); masm->j(less, &fast);
// Adjust 'addr' to be relative to the start of the extra remembered set // Adjust 'page_start' so that addressing using 'pointer_offset' hits the
// and the page address in 'object' to be the address of the extra // extra remembered set after the large object.
// remembered set.
masm->subq(addr, Immediate(Page::kPageSize / kPointerSize));
// Load the array length into 'scratch'. // Load the array length into 'scratch'.
masm->movl(scratch, masm->movl(scratch,
Operand(object, Operand(page_start,
Page::kObjectStartOffset + FixedArray::kLengthOffset)); Page::kObjectStartOffset + FixedArray::kLengthOffset));
// Extra remembered set starts right after FixedArray. Register array_length = scratch;
// Add the page header, array header, and array body size
// (length * pointer size) to the page address to find the extra remembered // Extra remembered set starts right after the large object (a FixedArray), at
// set start. // page_start + kObjectStartOffset + objectSize
masm->lea(object, // where objectSize is FixedArray::kHeaderSize + kPointerSize * array_length.
Operand(object, scratch, times_pointer_size, // Add the delta between the end of the normal RSet and the start of the
Page::kObjectStartOffset + FixedArray::kHeaderSize)); // extra RSet to 'page_start', so that addressing the bit using
// 'pointer_offset' hits the extra RSet words.
masm->lea(page_start,
Operand(page_start, array_length, times_pointer_size,
Page::kObjectStartOffset + FixedArray::kHeaderSize
- Page::kRSetEndOffset));
// NOTE: For now, we use the bit-test-and-set (bts) x86 instruction // NOTE: For now, we use the bit-test-and-set (bts) x86 instruction
// to limit code size. We should probably evaluate this decision by // to limit code size. We should probably evaluate this decision by
// measuring the performance of an equivalent implementation using // measuring the performance of an equivalent implementation using
// "simpler" instructions // "simpler" instructions
masm->bind(&fast); masm->bind(&fast);
masm->bts(Operand(object, Page::kRSetOffset), addr); masm->bts(Operand(page_start, Page::kRSetOffset), pointer_offset);
} }
...@@ -181,7 +188,7 @@ void MacroAssembler::RecordWrite(Register object, ...@@ -181,7 +188,7 @@ void MacroAssembler::RecordWrite(Register object,
} else { } else {
// array access: calculate the destination address in the same manner as // array access: calculate the destination address in the same manner as
// KeyedStoreIC::GenerateGeneric. Multiply a smi by 4 to get an offset // KeyedStoreIC::GenerateGeneric. Multiply a smi by 4 to get an offset
// into an array of words. // into an array of pointers.
lea(dst, Operand(object, dst, times_half_pointer_size, lea(dst, Operand(object, dst, times_half_pointer_size,
FixedArray::kHeaderSize - kHeapObjectTag)); FixedArray::kHeaderSize - kHeapObjectTag));
} }
......
...@@ -816,15 +816,3 @@ js1_5/extensions/regress-336410-2: CRASH ...@@ -816,15 +816,3 @@ js1_5/extensions/regress-336410-2: CRASH
js1_5/extensions/regress-336410-1: CRASH js1_5/extensions/regress-336410-1: CRASH
js1_5/Function/regress-338001: FAIL || CRASH js1_5/Function/regress-338001: FAIL || CRASH
js1_5/extensions/regress-371636: CRASH js1_5/extensions/regress-371636: CRASH
# The following failures were added when remembered sets were enabled.
js1_5/GC/regress-203278-2: FAIL || PASS || CRASH
js1_5/GC/regress-203278-3: FAIL || PASS
js1_5/Regress/regress-280769-3: FAIL || PASS
js1_5/Regress/regress-280769-4: CRASH || TIMEOUT
js1_5/Regress/regress-290575: CRASH
js1_5/extensions/regress-365692: FAIL || PASS
js1_5/Regress/regress-366601: FAIL
js1_5/Regress/regress-367561-03: CRASH
js1_5/Regress/regress-367561-01: CRASH || PASS
ecma/Expressions/11.7.2: CRASH
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment