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

Unified Diff: src/spaces.h

Issue 2071020: Reverting r4685, r4686, r4687 (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 10 years, 7 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
« no previous file with comments | « src/runtime.cc ('k') | src/spaces.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/spaces.h
===================================================================
--- src/spaces.h (revision 4686)
+++ src/spaces.h (working copy)
@@ -45,47 +45,24 @@
// The old generation is collected by a mark-sweep-compact collector.
//
// The semispaces of the young generation are contiguous. The old and map
-// spaces consists of a list of pages. A page has a page header and an object
-// area. A page size is deliberately chosen as 8K bytes.
-// The first word of a page is an opaque page header that has the
+// spaces consists of a list of pages. A page has a page header, a remembered
+// set area, and an object area. A page size is deliberately chosen as 8K
+// bytes. The first word of a page is an opaque page header that has the
// address of the next page and its ownership information. The second word may
-// have the allocation top address of this page. Heap objects are aligned to the
-// pointer size.
+// have the allocation top address of this page. The next 248 bytes are
+// remembered sets. Heap objects are aligned to the pointer size (4 bytes). A
+// remembered set bit corresponds to a pointer in the object area.
//
// There is a separate large object space for objects larger than
// Page::kMaxHeapObjectSize, so that they do not have to move during
-// collection. The large object space is paged. Pages in large object space
-// may be larger than 8K.
+// collection. The large object space is paged and uses the same remembered
+// set implementation. Pages in large object space may be larger than 8K.
//
-// A card marking write barrier is used to keep track of intergenerational
-// references. Old space pages are divided into regions of Page::kRegionSize
-// size. Each region has a corresponding dirty bit in the page header which is
-// set if the region might contain pointers to new space. For details about
-// dirty bits encoding see comments in the Page::GetRegionNumberForAddress()
-// method body.
-//
-// During scavenges and mark-sweep collections we iterate intergenerational
-// pointers without decoding heap object maps so if the page belongs to old
-// pointer space or large object space it is essential to guarantee that
-// the page does not contain any garbage pointers to new space: every pointer
-// aligned word which satisfies the Heap::InNewSpace() predicate must be a
-// pointer to a live heap object in new space. Thus objects in old pointer
-// and large object spaces should have a special layout (e.g. no bare integer
-// fields). This requirement does not apply to map space which is iterated in
-// a special fashion. However we still require pointer fields of dead maps to
-// be cleaned.
-//
-// To enable lazy cleaning of old space pages we use a notion of allocation
-// watermark. Every pointer under watermark is considered to be well formed.
-// Page allocation watermark is not necessarily equal to page allocation top but
-// all alive objects on page should reside under allocation watermark.
-// During scavenge allocation watermark might be bumped and invalid pointers
-// might appear below it. To avoid following them we store a valid watermark
-// into special field in the page header and set a page WATERMARK_INVALIDATED
-// flag. For details see comments in the Page::SetAllocationWatermark() method
-// body.
-//
+// NOTE: The mark-compact collector rebuilds the remembered set after a
+// collection. It reuses first a few words of the remembered set for
+// bookkeeping relocation information.
+
// Some assertion macros used in the debugging mode.
#define ASSERT_PAGE_ALIGNED(address) \
@@ -114,13 +91,25 @@
// -----------------------------------------------------------------------------
// A page normally has 8K bytes. Large object pages may be larger. A page
-// address is always aligned to the 8K page size.
+// address is always aligned to the 8K page size. A page is divided into
+// three areas: the first two words are used for bookkeeping, the next 248
+// bytes are used as remembered set, and the rest of the page is the object
+// area.
//
-// Each page starts with a header of Page::kPageHeaderSize size which contains
-// bookkeeping data.
+// Pointers are aligned to the pointer size (4), only 1 bit is needed
+// for a pointer in the remembered set. Given an address, its remembered set
+// bit position (offset from the start of the page) is calculated by dividing
+// its page offset by 32. Therefore, the object area in a page starts at the
+// 256th byte (8K/32). Bytes 0 to 255 do not need the remembered set, so that
+// the first two words (64 bits) in a page can be used for other purposes.
//
+// On the 64-bit platform, we add an offset to the start of the remembered set,
+// and pointers are aligned to 8-byte pointer size. This means that we need
+// only 128 bytes for the RSet, and only get two bytes free in the RSet's RSet.
+// For this reason we add an offset to get room for the Page data at the start.
+//
// The mark-compact collector transforms a map pointer into a page index and a
-// page offset. The exact encoding is described in the comments for
+// page offset. The excact encoding is described in the comments for
// class MapWord in objects.h.
//
// The only way to get a page pointer is by calling factory methods:
@@ -161,25 +150,18 @@
// Return the end of allocation in this page. Undefined for unused pages.
inline Address AllocationTop();
- // Return the allocation watermark for the page.
- // For old space pages it is guaranteed that the area under the watermark
- // does not contain any garbage pointers to new space.
- inline Address AllocationWatermark();
-
- // Return the allocation watermark offset from the beginning of the page.
- inline uint32_t AllocationWatermarkOffset();
-
- inline void SetAllocationWatermark(Address allocation_watermark);
-
- inline void SetCachedAllocationWatermark(Address allocation_watermark);
- inline Address CachedAllocationWatermark();
-
// Returns the start address of the object area in this page.
Address ObjectAreaStart() { return address() + kObjectStartOffset; }
// Returns the end address (exclusive) of the object area in this page.
Address ObjectAreaEnd() { return address() + Page::kPageSize; }
+ // Returns the start address of the remembered set area.
+ Address RSetStart() { return address() + kRSetStartOffset; }
+
+ // Returns the end address of the remembered set area (exclusive).
+ Address RSetEnd() { return address() + kRSetEndOffset; }
+
// Checks whether an address is page aligned.
static bool IsAlignedToPageSize(Address a) {
return 0 == (OffsetFrom(a) & kPageAlignmentMask);
@@ -211,99 +193,74 @@
}
// ---------------------------------------------------------------------
- // Card marking support
+ // Remembered set support
- static const uint32_t kAllRegionsCleanMarks = 0x0;
+ // Clears remembered set in this page.
+ inline void ClearRSet();
- inline uint32_t GetRegionMarks();
- inline void SetRegionMarks(uint32_t dirty);
+ // Return the address of the remembered set word corresponding to an
+ // object address/offset pair, and the bit encoded as a single-bit
+ // mask in the output parameter 'bitmask'.
+ INLINE(static Address ComputeRSetBitPosition(Address address, int offset,
+ uint32_t* bitmask));
- inline uint32_t GetRegionMaskForAddress(Address addr);
- inline int GetRegionNumberForAddress(Address addr);
+ // Sets the corresponding remembered set bit for a given address.
+ INLINE(static void SetRSet(Address address, int offset));
- inline void MarkRegionDirty(Address addr);
- inline bool IsRegionDirty(Address addr);
+ // Clears the corresponding remembered set bit for a given address.
+ static inline void UnsetRSet(Address address, int offset);
- inline void ClearRegionMarks(Address start,
- Address end,
- bool reaches_limit);
+ // Checks whether the remembered set bit for a given address is set.
+ static inline bool IsRSetSet(Address address, int offset);
+#ifdef DEBUG
+ // Use a state to mark whether remembered set space can be used for other
+ // purposes.
+ enum RSetState { IN_USE, NOT_IN_USE };
+ static bool is_rset_in_use() { return rset_state_ == IN_USE; }
+ static void set_rset_state(RSetState state) { rset_state_ = state; }
+#endif
+
// Page size in bytes. This must be a multiple of the OS page size.
static const int kPageSize = 1 << kPageSizeBits;
// Page size mask.
static const intptr_t kPageAlignmentMask = (1 << kPageSizeBits) - 1;
- static const int kPageHeaderSize = kPointerSize + kPointerSize + kIntSize +
- kIntSize + kPointerSize;
+ // The offset of the remembered set in a page, in addition to the empty bytes
+ // formed as the remembered bits of the remembered set itself.
+#ifdef V8_TARGET_ARCH_X64
+ static const int kRSetOffset = 4 * kPointerSize; // Room for four pointers.
+#else
+ static const int kRSetOffset = 0;
+#endif
+ // The end offset of the remembered set in a page
+ // (heaps are aligned to pointer size).
+ static const int kRSetEndOffset = kRSetOffset + kPageSize / kBitsPerPointer;
// The start offset of the object area in a page.
- static const int kObjectStartOffset = MAP_POINTER_ALIGN(kPageHeaderSize);
+ // This needs to be at least (bits per uint32_t) * kBitsPerPointer,
+ // to align start of rset to a uint32_t address.
+ static const int kObjectStartOffset = 256;
+ // The start offset of the used part of the remembered set in a page.
+ static const int kRSetStartOffset = kRSetOffset +
+ kObjectStartOffset / kBitsPerPointer;
+
// Object area size in bytes.
static const int kObjectAreaSize = kPageSize - kObjectStartOffset;
// Maximum object size that fits in a page.
static const int kMaxHeapObjectSize = kObjectAreaSize;
- static const int kDirtyFlagOffset = 2 * kPointerSize;
- static const int kRegionSizeLog2 = 8;
- static const int kRegionSize = 1 << kRegionSizeLog2;
- static const intptr_t kRegionAlignmentMask = (kRegionSize - 1);
-
- STATIC_CHECK(kRegionSize == kPageSize / kBitsPerInt);
-
enum PageFlag {
IS_NORMAL_PAGE = 1 << 0,
- WAS_IN_USE_BEFORE_MC = 1 << 1,
-
- // Page allocation watermark was bumped by preallocation during scavenge.
- // Correct watermark can be retrieved by CachedAllocationWatermark() method
- WATERMARK_INVALIDATED = 1 << 2
+ WAS_IN_USE_BEFORE_MC = 1 << 1
};
- // To avoid an additional WATERMARK_INVALIDATED flag clearing pass during
- // scavenge we just invalidate the watermark on each old space page after
- // processing it. And then we flip the meaning of the WATERMARK_INVALIDATED
- // flag at the beginning of the next scavenge and each page becomes marked as
- // having a valid watermark.
- //
- // The following invariant must hold for pages in old pointer and map spaces:
- // If page is in use then page is marked as having invalid watermark at
- // the beginning and at the end of any GC.
- //
- // This invariant guarantees that after flipping flag meaning at the
- // beginning of scavenge all pages in use will be marked as having valid
- // watermark.
- static inline void FlipMeaningOfInvalidatedWatermarkFlag();
-
- // Returns true if the page allocation watermark was not altered during
- // scavenge.
- inline bool IsWatermarkValid();
-
- inline void InvalidateWatermark(bool value);
-
inline bool GetPageFlag(PageFlag flag);
inline void SetPageFlag(PageFlag flag, bool value);
- inline void ClearPageFlags();
- static const int kAllocationWatermarkOffsetShift = 3;
- static const int kAllocationWatermarkOffsetBits = kPageSizeBits + 1;
- static const uint32_t kAllocationWatermarkOffsetMask =
- ((1 << kAllocationWatermarkOffsetBits) - 1) <<
- kAllocationWatermarkOffsetShift;
-
- static const uint32_t kFlagsMask =
- ((1 << kAllocationWatermarkOffsetShift) - 1);
-
- STATIC_CHECK(kBitsPerInt - kAllocationWatermarkOffsetShift >=
- kAllocationWatermarkOffsetBits);
-
- // This field contains the meaning of the WATERMARK_INVALIDATED flag.
- // Instead of clearing this flag from all pages we just flip
- // its meaning at the beginning of a scavenge.
- static intptr_t watermark_invalidated_mark_;
-
//---------------------------------------------------------------------------
// Page header description.
//
@@ -322,24 +279,26 @@
// second word *may* (if the page start and large object chunk start are
// the same) contain the large object chunk size. In either case, the
// low-order bit for large object pages will be cleared.
- // For normal pages this word is used to store page flags and
- // offset of allocation top.
- intptr_t flags_;
+ // For normal pages this word is used to store various page flags.
+ int flags;
- // This field contains dirty marks for regions covering the page. Only dirty
- // regions might contain intergenerational references.
- // Only 32 dirty marks are supported so for large object pages several regions
- // might be mapped to a single dirty mark.
- uint32_t dirty_regions_;
+ // The following fields may overlap with remembered set, they can only
+ // be used in the mark-compact collector when remembered set is not
+ // used.
// The index of the page in its owner space.
int mc_page_index;
- // During mark-compact collections this field contains the forwarding address
- // of the first live object in this page.
- // During scavenge collection this field is used to store allocation watermark
- // if it is altered during scavenge.
+ // The allocation pointer after relocating objects to this page.
+ Address mc_relocation_top;
+
+ // The forwarding address of the first live object in this page.
Address mc_first_forwarded;
+
+#ifdef DEBUG
+ private:
+ static RSetState rset_state_; // state of the remembered set
+#endif
};
@@ -962,7 +921,8 @@
// Checks whether page is currently in use by this space.
bool IsUsed(Page* page);
- void MarkAllPagesClean();
+ // Clears remembered sets of pages in this space.
+ void ClearRSet();
// Prepares for a mark-compact GC.
virtual void PrepareForMarkCompact(bool will_compact);
@@ -976,11 +936,6 @@
// The limit of allocation for a page in this space.
virtual Address PageAllocationLimit(Page* page) = 0;
- void FlushTopPageWatermark() {
- AllocationTopPage()->SetCachedAllocationWatermark(top());
- AllocationTopPage()->InvalidateWatermark(true);
- }
-
// Current capacity without growing (Size() + Available() + Waste()).
int Capacity() { return accounting_stats_.Capacity(); }
@@ -1035,8 +990,7 @@
// Writes relocation info to the top page.
void MCWriteRelocationInfoToPage() {
- TopPageOf(mc_forwarding_info_)->
- SetAllocationWatermark(mc_forwarding_info_.top);
+ TopPageOf(mc_forwarding_info_)->mc_relocation_top = mc_forwarding_info_.top;
}
// Computes the offset of a given address in this space to the beginning
@@ -1154,6 +1108,8 @@
#ifdef DEBUG
// Returns the number of total pages in this space.
int CountTotalPages();
+
+ void DoPrintRSet(const char* space_name);
#endif
private:
@@ -1790,10 +1746,6 @@
if (add_to_freelist) {
int wasted_bytes = free_list_.Free(start, size_in_bytes);
accounting_stats_.WasteBytes(wasted_bytes);
- } else {
-#ifdef DEBUG
- MemoryAllocator::ZapBlock(start, size_in_bytes);
-#endif
}
}
@@ -1810,6 +1762,8 @@
#ifdef DEBUG
// Reports statistics for the space
void ReportStatistics();
+ // Dump the remembered sets in the space to stdout.
+ void PrintRSet();
#endif
protected:
@@ -1858,10 +1812,6 @@
void Free(Address start, bool add_to_freelist) {
if (add_to_freelist) {
free_list_.Free(start);
- } else {
-#ifdef DEBUG
- MemoryAllocator::ZapBlock(start, object_size_in_bytes_);
-#endif
}
accounting_stats_.DeallocateBytes(object_size_in_bytes_);
}
@@ -1878,6 +1828,9 @@
#ifdef DEBUG
// Reports statistic info of the space
void ReportStatistics();
+
+ // Dump the remembered sets in the space to stdout.
+ void PrintRSet();
#endif
protected:
@@ -1946,11 +1899,11 @@
PageIterator it(this, PageIterator::ALL_PAGES);
while (pages_left-- > 0) {
ASSERT(it.has_next());
- it.next()->SetRegionMarks(Page::kAllRegionsCleanMarks);
+ it.next()->ClearRSet();
}
ASSERT(it.has_next());
Page* top_page = it.next();
- top_page->SetRegionMarks(Page::kAllRegionsCleanMarks);
+ top_page->ClearRSet();
ASSERT(top_page->is_valid());
int offset = live_maps % kMapsPerPage * Map::kSize;
@@ -2041,8 +1994,9 @@
public:
// Allocates a new LargeObjectChunk that contains a large object page
// (Page::kPageSize aligned) that has at least size_in_bytes (for a large
- // object) bytes after the object area start of that page.
- // The allocated chunk size is set in the output parameter chunk_size.
+ // object and possibly extra remembered set words) bytes after the object
+ // area start of that page. The allocated chunk size is set in the output
+ // parameter chunk_size.
static LargeObjectChunk* New(int size_in_bytes,
size_t* chunk_size,
Executability executable);
@@ -2065,12 +2019,16 @@
// Returns the object in this chunk.
inline HeapObject* GetObject();
- // Given a requested size returns the physical size of a chunk to be
- // allocated.
+ // Given a requested size (including any extra remembered set words),
+ // returns the physical size of a chunk to be allocated.
static int ChunkSizeFor(int size_in_bytes);
- // Given a chunk size, returns the object size it can accommodate. Used by
- // LargeObjectSpace::Available.
+ // Given a chunk size, returns the object size it can accommodate (not
+ // including any extra remembered set words). Used by
+ // LargeObjectSpace::Available. Note that this can overestimate the size
+ // of object that will fit in a chunk---if the object requires extra
+ // remembered set words (eg, for large fixed arrays), the actual object
+ // size for the chunk will be smaller than reported by this function.
static int ObjectSizeFor(int chunk_size) {
if (chunk_size <= (Page::kPageSize + Page::kObjectStartOffset)) return 0;
return chunk_size - Page::kPageSize - Page::kObjectStartOffset;
@@ -2106,7 +2064,8 @@
// Allocates a large FixedArray.
Object* AllocateRawFixedArray(int size_in_bytes);
- // Available bytes for objects in this space.
+ // Available bytes for objects in this space, not including any extra
+ // remembered set words.
int Available() {
return LargeObjectChunk::ObjectSizeFor(MemoryAllocator::Available());
}
@@ -2124,9 +2083,12 @@
// space, may be slow.
Object* FindObject(Address a);
- // Iterates objects covered by dirty regions.
- void IterateDirtyRegions(ObjectSlotCallback func);
+ // Clears remembered sets.
+ void ClearRSet();
+ // Iterates objects whose remembered set bits are set.
+ void IterateRSet(ObjectSlotCallback func);
+
// Frees unmarked objects.
void FreeUnmarkedObjects();
@@ -2152,6 +2114,8 @@
virtual void Print();
void ReportStatistics();
void CollectCodeStatistics();
+ // Dump the remembered sets in the space to stdout.
+ void PrintRSet();
#endif
// Checks whether an address is in the object area in this space. It
// iterates all objects in the space. May be slow.
@@ -2170,6 +2134,10 @@
int object_size,
Executability executable);
+ // Returns the number of extra bytes (rounded up to the nearest full word)
+ // required for extra_object_bytes of extra pointers (in bytes).
+ static inline int ExtraRSetBytesFor(int extra_object_bytes);
+
friend class LargeObjectIterator;
public:
« no previous file with comments | « src/runtime.cc ('k') | src/spaces.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698