| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 96 #define ASSERT_PAGE_ALIGNED(address) \ | 96 #define ASSERT_PAGE_ALIGNED(address) \ |
| 97 ASSERT((OffsetFrom(address) & Page::kPageAlignmentMask) == 0) | 97 ASSERT((OffsetFrom(address) & Page::kPageAlignmentMask) == 0) |
| 98 | 98 |
| 99 #define ASSERT_OBJECT_ALIGNED(address) \ | 99 #define ASSERT_OBJECT_ALIGNED(address) \ |
| 100 ASSERT((OffsetFrom(address) & kObjectAlignmentMask) == 0) | 100 ASSERT((OffsetFrom(address) & kObjectAlignmentMask) == 0) |
| 101 | 101 |
| 102 #define ASSERT_MAP_ALIGNED(address) \ | 102 #define ASSERT_MAP_ALIGNED(address) \ |
| 103 ASSERT((OffsetFrom(address) & kMapAlignmentMask) == 0) | 103 ASSERT((OffsetFrom(address) & kMapAlignmentMask) == 0) |
| 104 | 104 |
| 105 #define ASSERT_OBJECT_SIZE(size) \ | 105 #define ASSERT_OBJECT_SIZE(size) \ |
| 106 ASSERT((0 < size) && (size <= Page::kMaxHeapObjectSize)) | 106 ASSERT((0 < size) && (size <= Page::kMaxNonCodeHeapObjectSize)) |
| 107 | 107 |
| 108 #define ASSERT_PAGE_OFFSET(offset) \ | 108 #define ASSERT_PAGE_OFFSET(offset) \ |
| 109 ASSERT((Page::kObjectStartOffset <= offset) \ | 109 ASSERT((Page::kObjectStartOffset <= offset) \ |
| 110 && (offset <= Page::kPageSize)) | 110 && (offset <= Page::kPageSize)) |
| 111 | 111 |
| 112 #define ASSERT_MAP_PAGE_INDEX(index) \ | 112 #define ASSERT_MAP_PAGE_INDEX(index) \ |
| 113 ASSERT((0 <= index) && (index <= MapSpace::kMaxMapPageIndex)) | 113 ASSERT((0 <= index) && (index <= MapSpace::kMaxMapPageIndex)) |
| 114 | 114 |
| 115 | 115 |
| 116 class PagedSpace; | 116 class PagedSpace; |
| (...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 354 ClearFlag(SCAN_ON_SCAVENGE); | 354 ClearFlag(SCAN_ON_SCAVENGE); |
| 355 } | 355 } |
| 356 } | 356 } |
| 357 inline void set_scan_on_scavenge(bool scan); | 357 inline void set_scan_on_scavenge(bool scan); |
| 358 | 358 |
| 359 int store_buffer_counter() { return store_buffer_counter_; } | 359 int store_buffer_counter() { return store_buffer_counter_; } |
| 360 void set_store_buffer_counter(int counter) { | 360 void set_store_buffer_counter(int counter) { |
| 361 store_buffer_counter_ = counter; | 361 store_buffer_counter_ = counter; |
| 362 } | 362 } |
| 363 | 363 |
| 364 Address body() { return address() + kObjectStartOffset; } | |
| 365 | |
| 366 Address body_limit() { return address() + size(); } | |
| 367 | |
| 368 int body_size() { return static_cast<int>(size() - kObjectStartOffset); } | |
| 369 | |
| 370 bool Contains(Address addr) { | 364 bool Contains(Address addr) { |
| 371 return addr >= body() && addr < address() + size(); | 365 return addr >= area_start() && addr < area_end(); |
| 372 } | 366 } |
| 373 | 367 |
| 374 // Checks whether addr can be a limit of addresses in this page. | 368 // Checks whether addr can be a limit of addresses in this page. |
| 375 // It's a limit if it's in the page, or if it's just after the | 369 // It's a limit if it's in the page, or if it's just after the |
| 376 // last byte of the page. | 370 // last byte of the page. |
| 377 bool ContainsLimit(Address addr) { | 371 bool ContainsLimit(Address addr) { |
| 378 return addr >= body() && addr <= address() + size(); | 372 return addr >= area_start() && addr <= area_end(); |
| 379 } | 373 } |
| 380 | 374 |
| 381 enum MemoryChunkFlags { | 375 enum MemoryChunkFlags { |
| 382 IS_EXECUTABLE, | 376 IS_EXECUTABLE, |
| 383 ABOUT_TO_BE_FREED, | 377 ABOUT_TO_BE_FREED, |
| 384 POINTERS_TO_HERE_ARE_INTERESTING, | 378 POINTERS_TO_HERE_ARE_INTERESTING, |
| 385 POINTERS_FROM_HERE_ARE_INTERESTING, | 379 POINTERS_FROM_HERE_ARE_INTERESTING, |
| 386 SCAN_ON_SCAVENGE, | 380 SCAN_ON_SCAVENGE, |
| 387 IN_FROM_SPACE, // Mutually exclusive with IN_TO_SPACE. | 381 IN_FROM_SPACE, // Mutually exclusive with IN_TO_SPACE. |
| 388 IN_TO_SPACE, // All pages in new space has one of these two set. | 382 IN_TO_SPACE, // All pages in new space has one of these two set. |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 477 } | 471 } |
| 478 | 472 |
| 479 static const intptr_t kAlignment = | 473 static const intptr_t kAlignment = |
| 480 (static_cast<uintptr_t>(1) << kPageSizeBits); | 474 (static_cast<uintptr_t>(1) << kPageSizeBits); |
| 481 | 475 |
| 482 static const intptr_t kAlignmentMask = kAlignment - 1; | 476 static const intptr_t kAlignmentMask = kAlignment - 1; |
| 483 | 477 |
| 484 static const intptr_t kSizeOffset = kPointerSize + kPointerSize; | 478 static const intptr_t kSizeOffset = kPointerSize + kPointerSize; |
| 485 | 479 |
| 486 static const intptr_t kLiveBytesOffset = | 480 static const intptr_t kLiveBytesOffset = |
| 487 kSizeOffset + kPointerSize + kPointerSize + kPointerSize + | 481 kSizeOffset + kPointerSize + kPointerSize + kPointerSize + |
| 488 kPointerSize + kPointerSize + kPointerSize + kIntSize; | 482 kPointerSize + kPointerSize + |
| 483 kPointerSize + kPointerSize + kPointerSize + kIntSize; |
| 489 | 484 |
| 490 static const size_t kSlotsBufferOffset = kLiveBytesOffset + kIntSize; | 485 static const size_t kSlotsBufferOffset = kLiveBytesOffset + kIntSize; |
| 491 | 486 |
| 492 static const size_t kHeaderSize = | 487 static const size_t kHeaderSize = |
| 493 kSlotsBufferOffset + kPointerSize + kPointerSize; | 488 kSlotsBufferOffset + kPointerSize + kPointerSize; |
| 494 | 489 |
| 495 static const int kBodyOffset = | 490 static const int kBodyOffset = |
| 496 CODE_POINTER_ALIGN(MAP_POINTER_ALIGN(kHeaderSize + Bitmap::kSize)); | 491 CODE_POINTER_ALIGN(MAP_POINTER_ALIGN(kHeaderSize + Bitmap::kSize)); |
| 497 | 492 |
| 498 // The start offset of the object area in a page. Aligned to both maps and | 493 // The start offset of the object area in a page. Aligned to both maps and |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 584 void MarkEvacuationCandidate() { | 579 void MarkEvacuationCandidate() { |
| 585 ASSERT(slots_buffer_ == NULL); | 580 ASSERT(slots_buffer_ == NULL); |
| 586 SetFlag(EVACUATION_CANDIDATE); | 581 SetFlag(EVACUATION_CANDIDATE); |
| 587 } | 582 } |
| 588 | 583 |
| 589 void ClearEvacuationCandidate() { | 584 void ClearEvacuationCandidate() { |
| 590 ASSERT(slots_buffer_ == NULL); | 585 ASSERT(slots_buffer_ == NULL); |
| 591 ClearFlag(EVACUATION_CANDIDATE); | 586 ClearFlag(EVACUATION_CANDIDATE); |
| 592 } | 587 } |
| 593 | 588 |
| 589 Address area_start() { return area_start_; } |
| 590 Address area_end() { return area_end_; } |
| 591 int area_size() { |
| 592 return static_cast<int>(area_end() - area_start()); |
| 593 } |
| 594 | 594 |
| 595 protected: | 595 protected: |
| 596 MemoryChunk* next_chunk_; | 596 MemoryChunk* next_chunk_; |
| 597 MemoryChunk* prev_chunk_; | 597 MemoryChunk* prev_chunk_; |
| 598 size_t size_; | 598 size_t size_; |
| 599 intptr_t flags_; | 599 intptr_t flags_; |
| 600 |
| 601 // Start and end of allocatable memory on this chunk. |
| 602 Address area_start_; |
| 603 Address area_end_; |
| 604 |
| 600 // If the chunk needs to remember its memory reservation, it is stored here. | 605 // If the chunk needs to remember its memory reservation, it is stored here. |
| 601 VirtualMemory reservation_; | 606 VirtualMemory reservation_; |
| 602 // The identity of the owning space. This is tagged as a failure pointer, but | 607 // The identity of the owning space. This is tagged as a failure pointer, but |
| 603 // no failure can be in an object, so this can be distinguished from any entry | 608 // no failure can be in an object, so this can be distinguished from any entry |
| 604 // in a fixed array. | 609 // in a fixed array. |
| 605 Address owner_; | 610 Address owner_; |
| 606 Heap* heap_; | 611 Heap* heap_; |
| 607 // Used by the store buffer to keep track of which pages to mark scan-on- | 612 // Used by the store buffer to keep track of which pages to mark scan-on- |
| 608 // scavenge. | 613 // scavenge. |
| 609 int store_buffer_counter_; | 614 int store_buffer_counter_; |
| 610 // Count of bytes marked black on page. | 615 // Count of bytes marked black on page. |
| 611 int live_byte_count_; | 616 int live_byte_count_; |
| 612 SlotsBuffer* slots_buffer_; | 617 SlotsBuffer* slots_buffer_; |
| 613 SkipList* skip_list_; | 618 SkipList* skip_list_; |
| 614 | 619 |
| 615 static MemoryChunk* Initialize(Heap* heap, | 620 static MemoryChunk* Initialize(Heap* heap, |
| 616 Address base, | 621 Address base, |
| 617 size_t size, | 622 size_t size, |
| 623 Address area_start, |
| 624 Address area_end, |
| 618 Executability executable, | 625 Executability executable, |
| 619 Space* owner); | 626 Space* owner); |
| 620 | 627 |
| 621 friend class MemoryAllocator; | 628 friend class MemoryAllocator; |
| 622 }; | 629 }; |
| 623 | 630 |
| 624 STATIC_CHECK(sizeof(MemoryChunk) <= MemoryChunk::kHeaderSize); | 631 STATIC_CHECK(sizeof(MemoryChunk) <= MemoryChunk::kHeaderSize); |
| 625 | 632 |
| 626 // ----------------------------------------------------------------------------- | 633 // ----------------------------------------------------------------------------- |
| 627 // A page is a memory chunk of a size 1MB. Large object pages may be larger. | 634 // A page is a memory chunk of a size 1MB. Large object pages may be larger. |
| (...skipping 19 matching lines...) Expand all Loading... |
| 647 Page* p = FromAddress(top - kPointerSize); | 654 Page* p = FromAddress(top - kPointerSize); |
| 648 return p; | 655 return p; |
| 649 } | 656 } |
| 650 | 657 |
| 651 // Returns the next page in the chain of pages owned by a space. | 658 // Returns the next page in the chain of pages owned by a space. |
| 652 inline Page* next_page(); | 659 inline Page* next_page(); |
| 653 inline Page* prev_page(); | 660 inline Page* prev_page(); |
| 654 inline void set_next_page(Page* page); | 661 inline void set_next_page(Page* page); |
| 655 inline void set_prev_page(Page* page); | 662 inline void set_prev_page(Page* page); |
| 656 | 663 |
| 657 // Returns the start address of the object area in this page. | |
| 658 Address ObjectAreaStart() { return address() + kObjectStartOffset; } | |
| 659 | |
| 660 // Returns the end address (exclusive) of the object area in this page. | |
| 661 Address ObjectAreaEnd() { return address() + Page::kPageSize; } | |
| 662 | |
| 663 // Checks whether an address is page aligned. | 664 // Checks whether an address is page aligned. |
| 664 static bool IsAlignedToPageSize(Address a) { | 665 static bool IsAlignedToPageSize(Address a) { |
| 665 return 0 == (OffsetFrom(a) & kPageAlignmentMask); | 666 return 0 == (OffsetFrom(a) & kPageAlignmentMask); |
| 666 } | 667 } |
| 667 | 668 |
| 668 // Returns the offset of a given address to this page. | 669 // Returns the offset of a given address to this page. |
| 669 INLINE(int Offset(Address a)) { | 670 INLINE(int Offset(Address a)) { |
| 670 int offset = static_cast<int>(a - address()); | 671 int offset = static_cast<int>(a - address()); |
| 671 return offset; | 672 return offset; |
| 672 } | 673 } |
| 673 | 674 |
| 674 // Returns the address for a given offset to the this page. | 675 // Returns the address for a given offset to the this page. |
| 675 Address OffsetToAddress(int offset) { | 676 Address OffsetToAddress(int offset) { |
| 676 ASSERT_PAGE_OFFSET(offset); | 677 ASSERT_PAGE_OFFSET(offset); |
| 677 return address() + offset; | 678 return address() + offset; |
| 678 } | 679 } |
| 679 | 680 |
| 680 // --------------------------------------------------------------------- | 681 // --------------------------------------------------------------------- |
| 681 | 682 |
| 682 // Page size in bytes. This must be a multiple of the OS page size. | 683 // Page size in bytes. This must be a multiple of the OS page size. |
| 683 static const int kPageSize = 1 << kPageSizeBits; | 684 static const int kPageSize = 1 << kPageSizeBits; |
| 684 | 685 |
| 686 // Object area size in bytes. |
| 687 static const int kNonCodeObjectAreaSize = kPageSize - kObjectStartOffset; |
| 688 |
| 689 // Maximum object size that fits in a page. |
| 690 static const int kMaxNonCodeHeapObjectSize = kNonCodeObjectAreaSize; |
| 691 |
| 685 // Page size mask. | 692 // Page size mask. |
| 686 static const intptr_t kPageAlignmentMask = (1 << kPageSizeBits) - 1; | 693 static const intptr_t kPageAlignmentMask = (1 << kPageSizeBits) - 1; |
| 687 | 694 |
| 688 // Object area size in bytes. | |
| 689 static const int kObjectAreaSize = kPageSize - kObjectStartOffset; | |
| 690 | |
| 691 // Maximum object size that fits in a page. | |
| 692 static const int kMaxHeapObjectSize = kObjectAreaSize; | |
| 693 | |
| 694 static const int kFirstUsedCell = | |
| 695 (kObjectStartOffset/kPointerSize) >> Bitmap::kBitsPerCellLog2; | |
| 696 | |
| 697 static const int kLastUsedCell = | |
| 698 ((kPageSize - kPointerSize)/kPointerSize) >> | |
| 699 Bitmap::kBitsPerCellLog2; | |
| 700 | |
| 701 inline void ClearGCFields(); | 695 inline void ClearGCFields(); |
| 702 | 696 |
| 703 static inline Page* Initialize(Heap* heap, | 697 static inline Page* Initialize(Heap* heap, |
| 704 MemoryChunk* chunk, | 698 MemoryChunk* chunk, |
| 705 Executability executable, | 699 Executability executable, |
| 706 PagedSpace* owner); | 700 PagedSpace* owner); |
| 707 | 701 |
| 708 void InitializeAsAnchor(PagedSpace* owner); | 702 void InitializeAsAnchor(PagedSpace* owner); |
| 709 | 703 |
| 710 bool WasSweptPrecisely() { return IsFlagSet(WAS_SWEPT_PRECISELY); } | 704 bool WasSweptPrecisely() { return IsFlagSet(WAS_SWEPT_PRECISELY); } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 724 friend class MemoryAllocator; | 718 friend class MemoryAllocator; |
| 725 }; | 719 }; |
| 726 | 720 |
| 727 | 721 |
| 728 STATIC_CHECK(sizeof(Page) <= MemoryChunk::kHeaderSize); | 722 STATIC_CHECK(sizeof(Page) <= MemoryChunk::kHeaderSize); |
| 729 | 723 |
| 730 | 724 |
| 731 class LargePage : public MemoryChunk { | 725 class LargePage : public MemoryChunk { |
| 732 public: | 726 public: |
| 733 HeapObject* GetObject() { | 727 HeapObject* GetObject() { |
| 734 return HeapObject::FromAddress(body()); | 728 return HeapObject::FromAddress(area_start()); |
| 735 } | 729 } |
| 736 | 730 |
| 737 inline LargePage* next_page() const { | 731 inline LargePage* next_page() const { |
| 738 return static_cast<LargePage*>(next_chunk()); | 732 return static_cast<LargePage*>(next_chunk()); |
| 739 } | 733 } |
| 740 | 734 |
| 741 inline void set_next_page(LargePage* page) { | 735 inline void set_next_page(LargePage* page) { |
| 742 set_next_chunk(page); | 736 set_next_chunk(page); |
| 743 } | 737 } |
| 744 private: | 738 private: |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 965 intptr_t AvailableExecutable() { | 959 intptr_t AvailableExecutable() { |
| 966 if (capacity_executable_ < size_executable_) return 0; | 960 if (capacity_executable_ < size_executable_) return 0; |
| 967 return capacity_executable_ - size_executable_; | 961 return capacity_executable_ - size_executable_; |
| 968 } | 962 } |
| 969 | 963 |
| 970 // Returns allocated executable spaces in bytes. | 964 // Returns allocated executable spaces in bytes. |
| 971 intptr_t SizeExecutable() { return size_executable_; } | 965 intptr_t SizeExecutable() { return size_executable_; } |
| 972 | 966 |
| 973 // Returns maximum available bytes that the old space can have. | 967 // Returns maximum available bytes that the old space can have. |
| 974 intptr_t MaxAvailable() { | 968 intptr_t MaxAvailable() { |
| 975 return (Available() / Page::kPageSize) * Page::kObjectAreaSize; | 969 return (Available() / Page::kPageSize) * Page::kMaxNonCodeHeapObjectSize; |
| 976 } | 970 } |
| 977 | 971 |
| 978 #ifdef DEBUG | 972 #ifdef DEBUG |
| 979 // Reports statistic info of the space. | 973 // Reports statistic info of the space. |
| 980 void ReportStatistics(); | 974 void ReportStatistics(); |
| 981 #endif | 975 #endif |
| 982 | 976 |
| 983 MemoryChunk* AllocateChunk(intptr_t body_size, | 977 MemoryChunk* AllocateChunk(intptr_t body_size, |
| 984 Executability executable, | 978 Executability executable, |
| 985 Space* space); | 979 Space* space); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1018 void AddMemoryAllocationCallback(MemoryAllocationCallback callback, | 1012 void AddMemoryAllocationCallback(MemoryAllocationCallback callback, |
| 1019 ObjectSpace space, | 1013 ObjectSpace space, |
| 1020 AllocationAction action); | 1014 AllocationAction action); |
| 1021 | 1015 |
| 1022 void RemoveMemoryAllocationCallback( | 1016 void RemoveMemoryAllocationCallback( |
| 1023 MemoryAllocationCallback callback); | 1017 MemoryAllocationCallback callback); |
| 1024 | 1018 |
| 1025 bool MemoryAllocationCallbackRegistered( | 1019 bool MemoryAllocationCallbackRegistered( |
| 1026 MemoryAllocationCallback callback); | 1020 MemoryAllocationCallback callback); |
| 1027 | 1021 |
| 1022 static int CodePageGuardStartOffset(); |
| 1023 |
| 1024 static int CodePageGuardSize(); |
| 1025 |
| 1026 static int CodePageAreaStartOffset(); |
| 1027 |
| 1028 static int CodePageAreaEndOffset(); |
| 1029 |
| 1030 static int CodePageAreaSize() { |
| 1031 return CodePageAreaEndOffset() - CodePageAreaStartOffset(); |
| 1032 } |
| 1033 |
| 1034 static bool CommitCodePage(VirtualMemory* vm, Address start, size_t size); |
| 1035 |
| 1028 private: | 1036 private: |
| 1029 Isolate* isolate_; | 1037 Isolate* isolate_; |
| 1030 | 1038 |
| 1031 // Maximum space size in bytes. | 1039 // Maximum space size in bytes. |
| 1032 size_t capacity_; | 1040 size_t capacity_; |
| 1033 // Maximum subset of capacity_ that can be executable | 1041 // Maximum subset of capacity_ that can be executable |
| 1034 size_t capacity_executable_; | 1042 size_t capacity_executable_; |
| 1035 | 1043 |
| 1036 // Allocated space size in bytes. | 1044 // Allocated space size in bytes. |
| 1037 size_t size_; | 1045 size_t size_; |
| (...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1370 intptr_t huge_size_; | 1378 intptr_t huge_size_; |
| 1371 }; | 1379 }; |
| 1372 | 1380 |
| 1373 void CountFreeListItems(Page* p, SizeStats* sizes); | 1381 void CountFreeListItems(Page* p, SizeStats* sizes); |
| 1374 | 1382 |
| 1375 intptr_t EvictFreeListItems(Page* p); | 1383 intptr_t EvictFreeListItems(Page* p); |
| 1376 | 1384 |
| 1377 private: | 1385 private: |
| 1378 // The size range of blocks, in bytes. | 1386 // The size range of blocks, in bytes. |
| 1379 static const int kMinBlockSize = 3 * kPointerSize; | 1387 static const int kMinBlockSize = 3 * kPointerSize; |
| 1380 static const int kMaxBlockSize = Page::kMaxHeapObjectSize; | 1388 static const int kMaxBlockSize = Page::kMaxNonCodeHeapObjectSize; |
| 1381 | 1389 |
| 1382 FreeListNode* PickNodeFromList(FreeListNode** list, int* node_size); | 1390 FreeListNode* PickNodeFromList(FreeListNode** list, int* node_size); |
| 1383 | 1391 |
| 1384 FreeListNode* FindNodeFor(int size_in_bytes, int* node_size); | 1392 FreeListNode* FindNodeFor(int size_in_bytes, int* node_size); |
| 1385 | 1393 |
| 1386 PagedSpace* owner_; | 1394 PagedSpace* owner_; |
| 1387 Heap* heap_; | 1395 Heap* heap_; |
| 1388 | 1396 |
| 1389 // Total available bytes in all blocks on this free list. | 1397 // Total available bytes in all blocks on this free list. |
| 1390 int available_; | 1398 int available_; |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1574 // worth defragmenting them. Otherwise a positive integer that gives an | 1582 // worth defragmenting them. Otherwise a positive integer that gives an |
| 1575 // estimate of fragmentation on an arbitrary scale. | 1583 // estimate of fragmentation on an arbitrary scale. |
| 1576 int Fragmentation(Page* p) { | 1584 int Fragmentation(Page* p) { |
| 1577 FreeList::SizeStats sizes; | 1585 FreeList::SizeStats sizes; |
| 1578 free_list_.CountFreeListItems(p, &sizes); | 1586 free_list_.CountFreeListItems(p, &sizes); |
| 1579 | 1587 |
| 1580 intptr_t ratio; | 1588 intptr_t ratio; |
| 1581 intptr_t ratio_threshold; | 1589 intptr_t ratio_threshold; |
| 1582 if (identity() == CODE_SPACE) { | 1590 if (identity() == CODE_SPACE) { |
| 1583 ratio = (sizes.medium_size_ * 10 + sizes.large_size_ * 2) * 100 / | 1591 ratio = (sizes.medium_size_ * 10 + sizes.large_size_ * 2) * 100 / |
| 1584 Page::kObjectAreaSize; | 1592 AreaSize(); |
| 1585 ratio_threshold = 10; | 1593 ratio_threshold = 10; |
| 1586 } else { | 1594 } else { |
| 1587 ratio = (sizes.small_size_ * 5 + sizes.medium_size_) * 100 / | 1595 ratio = (sizes.small_size_ * 5 + sizes.medium_size_) * 100 / |
| 1588 Page::kObjectAreaSize; | 1596 AreaSize(); |
| 1589 ratio_threshold = 15; | 1597 ratio_threshold = 15; |
| 1590 } | 1598 } |
| 1591 | 1599 |
| 1592 if (FLAG_trace_fragmentation) { | 1600 if (FLAG_trace_fragmentation) { |
| 1593 PrintF("%p [%d]: %d (%.2f%%) %d (%.2f%%) %d (%.2f%%) %d (%.2f%%) %s\n", | 1601 PrintF("%p [%d]: %d (%.2f%%) %d (%.2f%%) %d (%.2f%%) %d (%.2f%%) %s\n", |
| 1594 reinterpret_cast<void*>(p), | 1602 reinterpret_cast<void*>(p), |
| 1595 identity(), | 1603 identity(), |
| 1596 static_cast<int>(sizes.small_size_), | 1604 static_cast<int>(sizes.small_size_), |
| 1597 static_cast<double>(sizes.small_size_ * 100) / | 1605 static_cast<double>(sizes.small_size_ * 100) / |
| 1598 Page::kObjectAreaSize, | 1606 AreaSize(), |
| 1599 static_cast<int>(sizes.medium_size_), | 1607 static_cast<int>(sizes.medium_size_), |
| 1600 static_cast<double>(sizes.medium_size_ * 100) / | 1608 static_cast<double>(sizes.medium_size_ * 100) / |
| 1601 Page::kObjectAreaSize, | 1609 AreaSize(), |
| 1602 static_cast<int>(sizes.large_size_), | 1610 static_cast<int>(sizes.large_size_), |
| 1603 static_cast<double>(sizes.large_size_ * 100) / | 1611 static_cast<double>(sizes.large_size_ * 100) / |
| 1604 Page::kObjectAreaSize, | 1612 AreaSize(), |
| 1605 static_cast<int>(sizes.huge_size_), | 1613 static_cast<int>(sizes.huge_size_), |
| 1606 static_cast<double>(sizes.huge_size_ * 100) / | 1614 static_cast<double>(sizes.huge_size_ * 100) / |
| 1607 Page::kObjectAreaSize, | 1615 AreaSize(), |
| 1608 (ratio > ratio_threshold) ? "[fragmented]" : ""); | 1616 (ratio > ratio_threshold) ? "[fragmented]" : ""); |
| 1609 } | 1617 } |
| 1610 | 1618 |
| 1611 if (FLAG_always_compact && sizes.Total() != Page::kObjectAreaSize) { | 1619 if (FLAG_always_compact && sizes.Total() != AreaSize()) { |
| 1612 return 1; | 1620 return 1; |
| 1613 } | 1621 } |
| 1614 if (ratio <= ratio_threshold) return 0; // Not fragmented. | 1622 if (ratio <= ratio_threshold) return 0; // Not fragmented. |
| 1615 | 1623 |
| 1616 return static_cast<int>(ratio - ratio_threshold); | 1624 return static_cast<int>(ratio - ratio_threshold); |
| 1617 } | 1625 } |
| 1618 | 1626 |
| 1619 void EvictEvacuationCandidatesFromFreeLists(); | 1627 void EvictEvacuationCandidatesFromFreeLists(); |
| 1620 | 1628 |
| 1621 bool CanExpand(); | 1629 bool CanExpand(); |
| 1622 | 1630 |
| 1623 // Returns the number of total pages in this space. | 1631 // Returns the number of total pages in this space. |
| 1624 int CountTotalPages(); | 1632 int CountTotalPages(); |
| 1625 | 1633 |
| 1634 // Return size of allocatable area on a page in this space. |
| 1635 inline int AreaSize() { |
| 1636 return area_size_; |
| 1637 } |
| 1638 |
| 1626 protected: | 1639 protected: |
| 1640 int area_size_; |
| 1641 |
| 1627 // Maximum capacity of this space. | 1642 // Maximum capacity of this space. |
| 1628 intptr_t max_capacity_; | 1643 intptr_t max_capacity_; |
| 1629 | 1644 |
| 1630 // Accounting information for this space. | 1645 // Accounting information for this space. |
| 1631 AllocationStats accounting_stats_; | 1646 AllocationStats accounting_stats_; |
| 1632 | 1647 |
| 1633 // The dummy page that anchors the double linked list of pages. | 1648 // The dummy page that anchors the double linked list of pages. |
| 1634 Page anchor_; | 1649 Page anchor_; |
| 1635 | 1650 |
| 1636 // The space's free list. | 1651 // The space's free list. |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1710 | 1725 |
| 1711 class NewSpacePage : public MemoryChunk { | 1726 class NewSpacePage : public MemoryChunk { |
| 1712 public: | 1727 public: |
| 1713 // GC related flags copied from from-space to to-space when | 1728 // GC related flags copied from from-space to to-space when |
| 1714 // flipping semispaces. | 1729 // flipping semispaces. |
| 1715 static const intptr_t kCopyOnFlipFlagsMask = | 1730 static const intptr_t kCopyOnFlipFlagsMask = |
| 1716 (1 << MemoryChunk::POINTERS_TO_HERE_ARE_INTERESTING) | | 1731 (1 << MemoryChunk::POINTERS_TO_HERE_ARE_INTERESTING) | |
| 1717 (1 << MemoryChunk::POINTERS_FROM_HERE_ARE_INTERESTING) | | 1732 (1 << MemoryChunk::POINTERS_FROM_HERE_ARE_INTERESTING) | |
| 1718 (1 << MemoryChunk::SCAN_ON_SCAVENGE); | 1733 (1 << MemoryChunk::SCAN_ON_SCAVENGE); |
| 1719 | 1734 |
| 1735 static const int kAreaSize = Page::kNonCodeObjectAreaSize; |
| 1736 |
| 1720 inline NewSpacePage* next_page() const { | 1737 inline NewSpacePage* next_page() const { |
| 1721 return static_cast<NewSpacePage*>(next_chunk()); | 1738 return static_cast<NewSpacePage*>(next_chunk()); |
| 1722 } | 1739 } |
| 1723 | 1740 |
| 1724 inline void set_next_page(NewSpacePage* page) { | 1741 inline void set_next_page(NewSpacePage* page) { |
| 1725 set_next_chunk(page); | 1742 set_next_chunk(page); |
| 1726 } | 1743 } |
| 1727 | 1744 |
| 1728 inline NewSpacePage* prev_page() const { | 1745 inline NewSpacePage* prev_page() const { |
| 1729 return static_cast<NewSpacePage*>(prev_chunk()); | 1746 return static_cast<NewSpacePage*>(prev_chunk()); |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1822 bool GrowTo(int new_capacity); | 1839 bool GrowTo(int new_capacity); |
| 1823 | 1840 |
| 1824 // Shrinks the semispace to the new capacity. The new capacity | 1841 // Shrinks the semispace to the new capacity. The new capacity |
| 1825 // requested must be more than the amount of used memory in the | 1842 // requested must be more than the amount of used memory in the |
| 1826 // semispace and less than the current capacity. | 1843 // semispace and less than the current capacity. |
| 1827 bool ShrinkTo(int new_capacity); | 1844 bool ShrinkTo(int new_capacity); |
| 1828 | 1845 |
| 1829 // Returns the start address of the first page of the space. | 1846 // Returns the start address of the first page of the space. |
| 1830 Address space_start() { | 1847 Address space_start() { |
| 1831 ASSERT(anchor_.next_page() != &anchor_); | 1848 ASSERT(anchor_.next_page() != &anchor_); |
| 1832 return anchor_.next_page()->body(); | 1849 return anchor_.next_page()->area_start(); |
| 1833 } | 1850 } |
| 1834 | 1851 |
| 1835 // Returns the start address of the current page of the space. | 1852 // Returns the start address of the current page of the space. |
| 1836 Address page_low() { | 1853 Address page_low() { |
| 1837 return current_page_->body(); | 1854 return current_page_->area_start(); |
| 1838 } | 1855 } |
| 1839 | 1856 |
| 1840 // Returns one past the end address of the space. | 1857 // Returns one past the end address of the space. |
| 1841 Address space_end() { | 1858 Address space_end() { |
| 1842 return anchor_.prev_page()->body_limit(); | 1859 return anchor_.prev_page()->area_end(); |
| 1843 } | 1860 } |
| 1844 | 1861 |
| 1845 // Returns one past the end address of the current page of the space. | 1862 // Returns one past the end address of the current page of the space. |
| 1846 Address page_high() { | 1863 Address page_high() { |
| 1847 return current_page_->body_limit(); | 1864 return current_page_->area_end(); |
| 1848 } | 1865 } |
| 1849 | 1866 |
| 1850 bool AdvancePage() { | 1867 bool AdvancePage() { |
| 1851 NewSpacePage* next_page = current_page_->next_page(); | 1868 NewSpacePage* next_page = current_page_->next_page(); |
| 1852 if (next_page == anchor()) return false; | 1869 if (next_page == anchor()) return false; |
| 1853 current_page_ = next_page; | 1870 current_page_ = next_page; |
| 1854 return true; | 1871 return true; |
| 1855 } | 1872 } |
| 1856 | 1873 |
| 1857 // Resets the space to using the first page. | 1874 // Resets the space to using the first page. |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1973 SemiSpaceIterator(NewSpace* space, Address start); | 1990 SemiSpaceIterator(NewSpace* space, Address start); |
| 1974 // Iterate from one address to another in the same semi-space. | 1991 // Iterate from one address to another in the same semi-space. |
| 1975 SemiSpaceIterator(Address from, Address to); | 1992 SemiSpaceIterator(Address from, Address to); |
| 1976 | 1993 |
| 1977 HeapObject* Next() { | 1994 HeapObject* Next() { |
| 1978 if (current_ == limit_) return NULL; | 1995 if (current_ == limit_) return NULL; |
| 1979 if (NewSpacePage::IsAtEnd(current_)) { | 1996 if (NewSpacePage::IsAtEnd(current_)) { |
| 1980 NewSpacePage* page = NewSpacePage::FromLimit(current_); | 1997 NewSpacePage* page = NewSpacePage::FromLimit(current_); |
| 1981 page = page->next_page(); | 1998 page = page->next_page(); |
| 1982 ASSERT(!page->is_anchor()); | 1999 ASSERT(!page->is_anchor()); |
| 1983 current_ = page->body(); | 2000 current_ = page->area_start(); |
| 1984 if (current_ == limit_) return NULL; | 2001 if (current_ == limit_) return NULL; |
| 1985 } | 2002 } |
| 1986 | 2003 |
| 1987 HeapObject* object = HeapObject::FromAddress(current_); | 2004 HeapObject* object = HeapObject::FromAddress(current_); |
| 1988 int size = (size_func_ == NULL) ? object->Size() : size_func_(object); | 2005 int size = (size_func_ == NULL) ? object->Size() : size_func_(object); |
| 1989 | 2006 |
| 1990 current_ += size; | 2007 current_ += size; |
| 1991 return object; | 2008 return object; |
| 1992 } | 2009 } |
| 1993 | 2010 |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2081 == reinterpret_cast<uintptr_t>(start_); | 2098 == reinterpret_cast<uintptr_t>(start_); |
| 2082 } | 2099 } |
| 2083 | 2100 |
| 2084 bool Contains(Object* o) { | 2101 bool Contains(Object* o) { |
| 2085 Address a = reinterpret_cast<Address>(o); | 2102 Address a = reinterpret_cast<Address>(o); |
| 2086 return (reinterpret_cast<uintptr_t>(a) & object_mask_) == object_expected_; | 2103 return (reinterpret_cast<uintptr_t>(a) & object_mask_) == object_expected_; |
| 2087 } | 2104 } |
| 2088 | 2105 |
| 2089 // Return the allocated bytes in the active semispace. | 2106 // Return the allocated bytes in the active semispace. |
| 2090 virtual intptr_t Size() { | 2107 virtual intptr_t Size() { |
| 2091 return pages_used_ * Page::kObjectAreaSize + | 2108 return pages_used_ * NewSpacePage::kAreaSize + |
| 2092 static_cast<int>(top() - to_space_.page_low()); | 2109 static_cast<int>(top() - to_space_.page_low()); |
| 2093 } | 2110 } |
| 2094 | 2111 |
| 2095 // The same, but returning an int. We have to have the one that returns | 2112 // The same, but returning an int. We have to have the one that returns |
| 2096 // intptr_t because it is inherited, but if we know we are dealing with the | 2113 // intptr_t because it is inherited, but if we know we are dealing with the |
| 2097 // new space, which can't get as big as the other spaces then this is useful: | 2114 // new space, which can't get as big as the other spaces then this is useful: |
| 2098 int SizeAsInt() { return static_cast<int>(Size()); } | 2115 int SizeAsInt() { return static_cast<int>(Size()); } |
| 2099 | 2116 |
| 2100 // Return the current capacity of a semispace. | 2117 // Return the current capacity of a semispace. |
| 2101 intptr_t EffectiveCapacity() { | 2118 intptr_t EffectiveCapacity() { |
| 2102 SLOW_ASSERT(to_space_.Capacity() == from_space_.Capacity()); | 2119 SLOW_ASSERT(to_space_.Capacity() == from_space_.Capacity()); |
| 2103 return (to_space_.Capacity() / Page::kPageSize) * Page::kObjectAreaSize; | 2120 return (to_space_.Capacity() / Page::kPageSize) * NewSpacePage::kAreaSize; |
| 2104 } | 2121 } |
| 2105 | 2122 |
| 2106 // Return the current capacity of a semispace. | 2123 // Return the current capacity of a semispace. |
| 2107 intptr_t Capacity() { | 2124 intptr_t Capacity() { |
| 2108 ASSERT(to_space_.Capacity() == from_space_.Capacity()); | 2125 ASSERT(to_space_.Capacity() == from_space_.Capacity()); |
| 2109 return to_space_.Capacity(); | 2126 return to_space_.Capacity(); |
| 2110 } | 2127 } |
| 2111 | 2128 |
| 2112 // Return the total amount of memory committed for new space. | 2129 // Return the total amount of memory committed for new space. |
| 2113 intptr_t CommittedMemory() { | 2130 intptr_t CommittedMemory() { |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2310 OldSpace(Heap* heap, | 2327 OldSpace(Heap* heap, |
| 2311 intptr_t max_capacity, | 2328 intptr_t max_capacity, |
| 2312 AllocationSpace id, | 2329 AllocationSpace id, |
| 2313 Executability executable) | 2330 Executability executable) |
| 2314 : PagedSpace(heap, max_capacity, id, executable) { | 2331 : PagedSpace(heap, max_capacity, id, executable) { |
| 2315 page_extra_ = 0; | 2332 page_extra_ = 0; |
| 2316 } | 2333 } |
| 2317 | 2334 |
| 2318 // The limit of allocation for a page in this space. | 2335 // The limit of allocation for a page in this space. |
| 2319 virtual Address PageAllocationLimit(Page* page) { | 2336 virtual Address PageAllocationLimit(Page* page) { |
| 2320 return page->ObjectAreaEnd(); | 2337 return page->area_end(); |
| 2321 } | 2338 } |
| 2322 | 2339 |
| 2323 public: | 2340 public: |
| 2324 TRACK_MEMORY("OldSpace") | 2341 TRACK_MEMORY("OldSpace") |
| 2325 }; | 2342 }; |
| 2326 | 2343 |
| 2327 | 2344 |
| 2328 // For contiguous spaces, top should be in the space (or at the end) and limit | 2345 // For contiguous spaces, top should be in the space (or at the end) and limit |
| 2329 // should be the end of the space. | 2346 // should be the end of the space. |
| 2330 #define ASSERT_SEMISPACE_ALLOCATION_INFO(info, space) \ | 2347 #define ASSERT_SEMISPACE_ALLOCATION_INFO(info, space) \ |
| 2331 SLOW_ASSERT((space).page_low() <= (info).top \ | 2348 SLOW_ASSERT((space).page_low() <= (info).top \ |
| 2332 && (info).top <= (space).page_high() \ | 2349 && (info).top <= (space).page_high() \ |
| 2333 && (info).limit <= (space).page_high()) | 2350 && (info).limit <= (space).page_high()) |
| 2334 | 2351 |
| 2335 | 2352 |
| 2336 // ----------------------------------------------------------------------------- | 2353 // ----------------------------------------------------------------------------- |
| 2337 // Old space for objects of a fixed size | 2354 // Old space for objects of a fixed size |
| 2338 | 2355 |
| 2339 class FixedSpace : public PagedSpace { | 2356 class FixedSpace : public PagedSpace { |
| 2340 public: | 2357 public: |
| 2341 FixedSpace(Heap* heap, | 2358 FixedSpace(Heap* heap, |
| 2342 intptr_t max_capacity, | 2359 intptr_t max_capacity, |
| 2343 AllocationSpace id, | 2360 AllocationSpace id, |
| 2344 int object_size_in_bytes, | 2361 int object_size_in_bytes, |
| 2345 const char* name) | 2362 const char* name) |
| 2346 : PagedSpace(heap, max_capacity, id, NOT_EXECUTABLE), | 2363 : PagedSpace(heap, max_capacity, id, NOT_EXECUTABLE), |
| 2347 object_size_in_bytes_(object_size_in_bytes), | 2364 object_size_in_bytes_(object_size_in_bytes), |
| 2348 name_(name) { | 2365 name_(name) { |
| 2349 page_extra_ = Page::kObjectAreaSize % object_size_in_bytes; | 2366 page_extra_ = Page::kNonCodeObjectAreaSize % object_size_in_bytes; |
| 2350 } | 2367 } |
| 2351 | 2368 |
| 2352 // The limit of allocation for a page in this space. | 2369 // The limit of allocation for a page in this space. |
| 2353 virtual Address PageAllocationLimit(Page* page) { | 2370 virtual Address PageAllocationLimit(Page* page) { |
| 2354 return page->ObjectAreaEnd() - page_extra_; | 2371 return page->area_end() - page_extra_; |
| 2355 } | 2372 } |
| 2356 | 2373 |
| 2357 int object_size_in_bytes() { return object_size_in_bytes_; } | 2374 int object_size_in_bytes() { return object_size_in_bytes_; } |
| 2358 | 2375 |
| 2359 // Prepares for a mark-compact GC. | 2376 // Prepares for a mark-compact GC. |
| 2360 virtual void PrepareForMarkCompact(); | 2377 virtual void PrepareForMarkCompact(); |
| 2361 | 2378 |
| 2362 protected: | 2379 protected: |
| 2363 void ResetFreeList() { | 2380 void ResetFreeList() { |
| 2364 free_list_.Reset(); | 2381 free_list_.Reset(); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2398 return (size / Map::kSize) * Map::kSize; | 2415 return (size / Map::kSize) * Map::kSize; |
| 2399 } | 2416 } |
| 2400 } | 2417 } |
| 2401 | 2418 |
| 2402 protected: | 2419 protected: |
| 2403 #ifdef DEBUG | 2420 #ifdef DEBUG |
| 2404 virtual void VerifyObject(HeapObject* obj); | 2421 virtual void VerifyObject(HeapObject* obj); |
| 2405 #endif | 2422 #endif |
| 2406 | 2423 |
| 2407 private: | 2424 private: |
| 2408 static const int kMapsPerPage = Page::kObjectAreaSize / Map::kSize; | 2425 static const int kMapsPerPage = Page::kNonCodeObjectAreaSize / Map::kSize; |
| 2409 | 2426 |
| 2410 // Do map space compaction if there is a page gap. | 2427 // Do map space compaction if there is a page gap. |
| 2411 int CompactionThreshold() { | 2428 int CompactionThreshold() { |
| 2412 return kMapsPerPage * (max_map_space_pages_ - 1); | 2429 return kMapsPerPage * (max_map_space_pages_ - 1); |
| 2413 } | 2430 } |
| 2414 | 2431 |
| 2415 const int max_map_space_pages_; | 2432 const int max_map_space_pages_; |
| 2416 | 2433 |
| 2417 public: | 2434 public: |
| 2418 TRACK_MEMORY("MapSpace") | 2435 TRACK_MEMORY("MapSpace") |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2629 } | 2646 } |
| 2630 // Must be small, since an iteration is used for lookup. | 2647 // Must be small, since an iteration is used for lookup. |
| 2631 static const int kMaxComments = 64; | 2648 static const int kMaxComments = 64; |
| 2632 }; | 2649 }; |
| 2633 #endif | 2650 #endif |
| 2634 | 2651 |
| 2635 | 2652 |
| 2636 } } // namespace v8::internal | 2653 } } // namespace v8::internal |
| 2637 | 2654 |
| 2638 #endif // V8_SPACES_H_ | 2655 #endif // V8_SPACES_H_ |
| OLD | NEW |