| Index: src/spaces.h
|
| diff --git a/src/spaces.h b/src/spaces.h
|
| index ee11b6b496efd27f74f5693cb124322401d4fbc6..770b88a9fba85e8ae8c37bee3880a63cf56a6f84 100644
|
| --- a/src/spaces.h
|
| +++ b/src/spaces.h
|
| @@ -103,7 +103,7 @@ class Isolate;
|
| ASSERT((OffsetFrom(address) & kObjectAlignmentMask) == 0)
|
|
|
| #define ASSERT_OBJECT_SIZE(size) \
|
| - ASSERT((0 < size) && (size <= Page::kMaxNonCodeHeapObjectSize))
|
| + ASSERT((0 < size) && (size <= Page::kMaxRegularHeapObjectSize))
|
|
|
| #define ASSERT_PAGE_OFFSET(offset) \
|
| ASSERT((Page::kObjectStartOffset <= offset) \
|
| @@ -313,11 +313,21 @@ class MemoryChunk {
|
|
|
| bool is_valid() { return address() != NULL; }
|
|
|
| - MemoryChunk* next_chunk() const { return next_chunk_; }
|
| - MemoryChunk* prev_chunk() const { return prev_chunk_; }
|
| + MemoryChunk* next_chunk() const {
|
| + return reinterpret_cast<MemoryChunk*>(Acquire_Load(&next_chunk_));
|
| + }
|
| +
|
| + MemoryChunk* prev_chunk() const {
|
| + return reinterpret_cast<MemoryChunk*>(Acquire_Load(&prev_chunk_));
|
| + }
|
|
|
| - void set_next_chunk(MemoryChunk* next) { next_chunk_ = next; }
|
| - void set_prev_chunk(MemoryChunk* prev) { prev_chunk_ = prev; }
|
| + void set_next_chunk(MemoryChunk* next) {
|
| + Release_Store(&next_chunk_, reinterpret_cast<AtomicWord>(next));
|
| + }
|
| +
|
| + void set_prev_chunk(MemoryChunk* prev) {
|
| + Release_Store(&prev_chunk_, reinterpret_cast<AtomicWord>(prev));
|
| + }
|
|
|
| Space* owner() const {
|
| if ((reinterpret_cast<intptr_t>(owner_) & kFailureTagMask) ==
|
| @@ -457,16 +467,32 @@ class MemoryChunk {
|
| // Return all current flags.
|
| intptr_t GetFlags() { return flags_; }
|
|
|
| - intptr_t parallel_sweeping() const {
|
| - return parallel_sweeping_;
|
| +
|
| + // PARALLEL_SWEEPING_PENDING - This page is ready for parallel sweeping.
|
| + // PARALLEL_SWEEPING_IN_PROGRESS - This page is currently swept or was
|
| + // swept by a sweeper thread.
|
| + // PARALLEL_SWEEPING_DONE - The page state when sweeping is complete or
|
| + // sweeping must not be performed on that page.
|
| + enum ParallelSweepingState {
|
| + PARALLEL_SWEEPING_DONE,
|
| + PARALLEL_SWEEPING_IN_PROGRESS,
|
| + PARALLEL_SWEEPING_PENDING
|
| + };
|
| +
|
| + ParallelSweepingState parallel_sweeping() {
|
| + return static_cast<ParallelSweepingState>(
|
| + NoBarrier_Load(¶llel_sweeping_));
|
| }
|
|
|
| - void set_parallel_sweeping(intptr_t state) {
|
| - parallel_sweeping_ = state;
|
| + void set_parallel_sweeping(ParallelSweepingState state) {
|
| + NoBarrier_Store(¶llel_sweeping_, state);
|
| }
|
|
|
| bool TryParallelSweeping() {
|
| - return NoBarrier_CompareAndSwap(¶llel_sweeping_, 1, 0) == 1;
|
| + return NoBarrier_CompareAndSwap(¶llel_sweeping_,
|
| + PARALLEL_SWEEPING_PENDING,
|
| + PARALLEL_SWEEPING_IN_PROGRESS) ==
|
| + PARALLEL_SWEEPING_PENDING;
|
| }
|
|
|
| // Manage live byte count (count of bytes known to be live,
|
| @@ -536,7 +562,7 @@ class MemoryChunk {
|
|
|
| static const intptr_t kAlignmentMask = kAlignment - 1;
|
|
|
| - static const intptr_t kSizeOffset = kPointerSize + kPointerSize;
|
| + static const intptr_t kSizeOffset = 0;
|
|
|
| static const intptr_t kLiveBytesOffset =
|
| kSizeOffset + kPointerSize + kPointerSize + kPointerSize +
|
| @@ -550,7 +576,8 @@ class MemoryChunk {
|
|
|
| static const size_t kHeaderSize = kWriteBarrierCounterOffset + kPointerSize +
|
| kIntSize + kIntSize + kPointerSize +
|
| - 5 * kPointerSize;
|
| + 5 * kPointerSize +
|
| + kPointerSize + kPointerSize;
|
|
|
| static const int kBodyOffset =
|
| CODE_POINTER_ALIGN(kHeaderSize + Bitmap::kSize);
|
| @@ -622,7 +649,7 @@ class MemoryChunk {
|
|
|
| inline Heap* heap() { return heap_; }
|
|
|
| - static const int kFlagsOffset = kPointerSize * 3;
|
| + static const int kFlagsOffset = kPointerSize;
|
|
|
| bool IsEvacuationCandidate() { return IsFlagSet(EVACUATION_CANDIDATE); }
|
|
|
| @@ -671,8 +698,6 @@ class MemoryChunk {
|
| static inline void UpdateHighWaterMark(Address mark);
|
|
|
| protected:
|
| - MemoryChunk* next_chunk_;
|
| - MemoryChunk* prev_chunk_;
|
| size_t size_;
|
| intptr_t flags_;
|
|
|
| @@ -702,7 +727,7 @@ class MemoryChunk {
|
| // count highest number of bytes ever allocated on the page.
|
| int high_water_mark_;
|
|
|
| - intptr_t parallel_sweeping_;
|
| + AtomicWord parallel_sweeping_;
|
|
|
| // PagedSpace free-list statistics.
|
| intptr_t available_in_small_free_list_;
|
| @@ -719,6 +744,12 @@ class MemoryChunk {
|
| Executability executable,
|
| Space* owner);
|
|
|
| + private:
|
| + // next_chunk_ holds a pointer of type MemoryChunk
|
| + AtomicWord next_chunk_;
|
| + // prev_chunk_ holds a pointer of type MemoryChunk
|
| + AtomicWord prev_chunk_;
|
| +
|
| friend class MemoryAllocator;
|
| };
|
|
|
| @@ -779,15 +810,11 @@ class Page : public MemoryChunk {
|
| // Page size in bytes. This must be a multiple of the OS page size.
|
| static const int kPageSize = 1 << kPageSizeBits;
|
|
|
| - // Object area size in bytes.
|
| - static const int kNonCodeObjectAreaSize = kPageSize - kObjectStartOffset;
|
| -
|
| // Maximum object size that fits in a page. Objects larger than that size
|
| // are allocated in large object space and are never moved in memory. This
|
| // also applies to new space allocation, since objects are never migrated
|
| // from new space to large object space. Takes double alignment into account.
|
| - static const int kMaxNonCodeHeapObjectSize =
|
| - kNonCodeObjectAreaSize - kPointerSize;
|
| + static const int kMaxRegularHeapObjectSize = kPageSize - kObjectStartOffset;
|
|
|
| // Page size mask.
|
| static const intptr_t kPageAlignmentMask = (1 << kPageSizeBits) - 1;
|
| @@ -1080,7 +1107,7 @@ class MemoryAllocator {
|
|
|
| // Returns maximum available bytes that the old space can have.
|
| intptr_t MaxAvailable() {
|
| - return (Available() / Page::kPageSize) * Page::kMaxNonCodeHeapObjectSize;
|
| + return (Available() / Page::kPageSize) * Page::kMaxRegularHeapObjectSize;
|
| }
|
|
|
| // Returns an indication of whether a pointer is in a space that has
|
| @@ -1507,7 +1534,7 @@ class FreeListNode: public HeapObject {
|
| class FreeListCategory {
|
| public:
|
| FreeListCategory() :
|
| - top_(NULL),
|
| + top_(0),
|
| end_(NULL),
|
| available_(0) {}
|
|
|
| @@ -1521,12 +1548,17 @@ class FreeListCategory {
|
| FreeListNode* PickNodeFromList(int size_in_bytes, int *node_size);
|
|
|
| intptr_t EvictFreeListItemsInList(Page* p);
|
| + bool ContainsPageFreeListItemsInList(Page* p);
|
|
|
| void RepairFreeList(Heap* heap);
|
|
|
| - FreeListNode** GetTopAddress() { return &top_; }
|
| - FreeListNode* top() const { return top_; }
|
| - void set_top(FreeListNode* top) { top_ = top; }
|
| + FreeListNode* top() const {
|
| + return reinterpret_cast<FreeListNode*>(NoBarrier_Load(&top_));
|
| + }
|
| +
|
| + void set_top(FreeListNode* top) {
|
| + NoBarrier_Store(&top_, reinterpret_cast<AtomicWord>(top));
|
| + }
|
|
|
| FreeListNode** GetEndAddress() { return &end_; }
|
| FreeListNode* end() const { return end_; }
|
| @@ -1538,13 +1570,18 @@ class FreeListCategory {
|
|
|
| Mutex* mutex() { return &mutex_; }
|
|
|
| + bool IsEmpty() {
|
| + return top() == 0;
|
| + }
|
| +
|
| #ifdef DEBUG
|
| intptr_t SumFreeList();
|
| int FreeListLength();
|
| #endif
|
|
|
| private:
|
| - FreeListNode* top_;
|
| + // top_ points to the top FreeListNode* in the free list category.
|
| + AtomicWord top_;
|
| FreeListNode* end_;
|
| Mutex mutex_;
|
|
|
| @@ -1576,7 +1613,7 @@ class FreeListCategory {
|
| // These spaces are call large.
|
| // At least 16384 words. This list is for objects of 2048 words or larger.
|
| // Empty pages are added to this list. These spaces are called huge.
|
| -class FreeList BASE_EMBEDDED {
|
| +class FreeList {
|
| public:
|
| explicit FreeList(PagedSpace* owner);
|
|
|
| @@ -1605,6 +1642,11 @@ class FreeList BASE_EMBEDDED {
|
| // 'wasted_bytes'. The size should be a non-zero multiple of the word size.
|
| MUST_USE_RESULT HeapObject* Allocate(int size_in_bytes);
|
|
|
| + bool IsEmpty() {
|
| + return small_list_.IsEmpty() && medium_list_.IsEmpty() &&
|
| + large_list_.IsEmpty() && huge_list_.IsEmpty();
|
| + }
|
| +
|
| #ifdef DEBUG
|
| void Zap();
|
| intptr_t SumFreeLists();
|
| @@ -1615,6 +1657,7 @@ class FreeList BASE_EMBEDDED {
|
| void RepairLists(Heap* heap);
|
|
|
| intptr_t EvictFreeListItems(Page* p);
|
| + bool ContainsPageFreeListItems(Page* p);
|
|
|
| FreeListCategory* small_list() { return &small_list_; }
|
| FreeListCategory* medium_list() { return &medium_list_; }
|
| @@ -1624,7 +1667,7 @@ class FreeList BASE_EMBEDDED {
|
| private:
|
| // The size range of blocks, in bytes.
|
| static const int kMinBlockSize = 3 * kPointerSize;
|
| - static const int kMaxBlockSize = Page::kMaxNonCodeHeapObjectSize;
|
| + static const int kMaxBlockSize = Page::kMaxRegularHeapObjectSize;
|
|
|
| FreeListNode* FindNodeFor(int size_in_bytes, int* node_size);
|
|
|
| @@ -1945,7 +1988,7 @@ class PagedSpace : public Space {
|
| MUST_USE_RESULT virtual HeapObject* SlowAllocateRaw(int size_in_bytes);
|
|
|
| friend class PageIterator;
|
| - friend class SweeperThread;
|
| + friend class MarkCompactCollector;
|
| };
|
|
|
|
|
| @@ -2002,7 +2045,7 @@ class NewSpacePage : public MemoryChunk {
|
| (1 << MemoryChunk::POINTERS_FROM_HERE_ARE_INTERESTING) |
|
| (1 << MemoryChunk::SCAN_ON_SCAVENGE);
|
|
|
| - static const int kAreaSize = Page::kNonCodeObjectAreaSize;
|
| + static const int kAreaSize = Page::kMaxRegularHeapObjectSize;
|
|
|
| inline NewSpacePage* next_page() const {
|
| return static_cast<NewSpacePage*>(next_chunk());
|
| @@ -2054,6 +2097,12 @@ class NewSpacePage : public MemoryChunk {
|
| return NewSpacePage::FromAddress(address_limit - 1);
|
| }
|
|
|
| + // Checks if address1 and address2 are on the same new space page.
|
| + static inline bool OnSamePage(Address address1, Address address2) {
|
| + return NewSpacePage::FromAddress(address1) ==
|
| + NewSpacePage::FromAddress(address2);
|
| + }
|
| +
|
| private:
|
| // Create a NewSpacePage object that is only used as anchor
|
| // for the doubly-linked list of real pages.
|
| @@ -2448,6 +2497,12 @@ class NewSpace : public Space {
|
| allocation_info_.set_top(top);
|
| }
|
|
|
| + // Return the address of the allocation pointer limit in the active semispace.
|
| + Address limit() {
|
| + ASSERT(to_space_.current_page()->ContainsLimit(allocation_info_.limit()));
|
| + return allocation_info_.limit();
|
| + }
|
| +
|
| // Return the address of the first object in the active semispace.
|
| Address bottom() { return to_space_.space_start(); }
|
|
|
| @@ -2662,7 +2717,7 @@ class MapSpace : public PagedSpace {
|
| virtual void VerifyObject(HeapObject* obj);
|
|
|
| private:
|
| - static const int kMapsPerPage = Page::kNonCodeObjectAreaSize / Map::kSize;
|
| + static const int kMapsPerPage = Page::kMaxRegularHeapObjectSize / Map::kSize;
|
|
|
| // Do map space compaction if there is a page gap.
|
| int CompactionThreshold() {
|
|
|