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 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
480 static void IncrementLiveBytesFromMutator(Address address, int by); | 474 static void IncrementLiveBytesFromMutator(Address address, int by); |
481 | 475 |
482 static const intptr_t kAlignment = | 476 static const intptr_t kAlignment = |
483 (static_cast<uintptr_t>(1) << kPageSizeBits); | 477 (static_cast<uintptr_t>(1) << kPageSizeBits); |
484 | 478 |
485 static const intptr_t kAlignmentMask = kAlignment - 1; | 479 static const intptr_t kAlignmentMask = kAlignment - 1; |
486 | 480 |
487 static const intptr_t kSizeOffset = kPointerSize + kPointerSize; | 481 static const intptr_t kSizeOffset = kPointerSize + kPointerSize; |
488 | 482 |
489 static const intptr_t kLiveBytesOffset = | 483 static const intptr_t kLiveBytesOffset = |
490 kSizeOffset + kPointerSize + kPointerSize + kPointerSize + | 484 kSizeOffset + kPointerSize + kPointerSize + kPointerSize + |
491 kPointerSize + kPointerSize + kPointerSize + kIntSize; | 485 kPointerSize + kPointerSize + |
| 486 kPointerSize + kPointerSize + kPointerSize + kIntSize; |
492 | 487 |
493 static const size_t kSlotsBufferOffset = kLiveBytesOffset + kIntSize; | 488 static const size_t kSlotsBufferOffset = kLiveBytesOffset + kIntSize; |
494 | 489 |
495 static const size_t kHeaderSize = | 490 static const size_t kHeaderSize = |
496 kSlotsBufferOffset + kPointerSize + kPointerSize; | 491 kSlotsBufferOffset + kPointerSize + kPointerSize; |
497 | 492 |
498 static const int kBodyOffset = | 493 static const int kBodyOffset = |
499 CODE_POINTER_ALIGN(MAP_POINTER_ALIGN(kHeaderSize + Bitmap::kSize)); | 494 CODE_POINTER_ALIGN(MAP_POINTER_ALIGN(kHeaderSize + Bitmap::kSize)); |
500 | 495 |
501 // The start offset of the object area in a page. Aligned to both maps and | 496 // 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... |
587 void MarkEvacuationCandidate() { | 582 void MarkEvacuationCandidate() { |
588 ASSERT(slots_buffer_ == NULL); | 583 ASSERT(slots_buffer_ == NULL); |
589 SetFlag(EVACUATION_CANDIDATE); | 584 SetFlag(EVACUATION_CANDIDATE); |
590 } | 585 } |
591 | 586 |
592 void ClearEvacuationCandidate() { | 587 void ClearEvacuationCandidate() { |
593 ASSERT(slots_buffer_ == NULL); | 588 ASSERT(slots_buffer_ == NULL); |
594 ClearFlag(EVACUATION_CANDIDATE); | 589 ClearFlag(EVACUATION_CANDIDATE); |
595 } | 590 } |
596 | 591 |
| 592 Address area_start() { return area_start_; } |
| 593 Address area_end() { return area_end_; } |
| 594 int area_size() { |
| 595 return static_cast<int>(area_end() - area_start()); |
| 596 } |
597 | 597 |
598 protected: | 598 protected: |
599 MemoryChunk* next_chunk_; | 599 MemoryChunk* next_chunk_; |
600 MemoryChunk* prev_chunk_; | 600 MemoryChunk* prev_chunk_; |
601 size_t size_; | 601 size_t size_; |
602 intptr_t flags_; | 602 intptr_t flags_; |
| 603 |
| 604 // Start and end of allocatable memory on this chunk. |
| 605 Address area_start_; |
| 606 Address area_end_; |
| 607 |
603 // If the chunk needs to remember its memory reservation, it is stored here. | 608 // If the chunk needs to remember its memory reservation, it is stored here. |
604 VirtualMemory reservation_; | 609 VirtualMemory reservation_; |
605 // The identity of the owning space. This is tagged as a failure pointer, but | 610 // The identity of the owning space. This is tagged as a failure pointer, but |
606 // no failure can be in an object, so this can be distinguished from any entry | 611 // no failure can be in an object, so this can be distinguished from any entry |
607 // in a fixed array. | 612 // in a fixed array. |
608 Address owner_; | 613 Address owner_; |
609 Heap* heap_; | 614 Heap* heap_; |
610 // Used by the store buffer to keep track of which pages to mark scan-on- | 615 // Used by the store buffer to keep track of which pages to mark scan-on- |
611 // scavenge. | 616 // scavenge. |
612 int store_buffer_counter_; | 617 int store_buffer_counter_; |
613 // Count of bytes marked black on page. | 618 // Count of bytes marked black on page. |
614 int live_byte_count_; | 619 int live_byte_count_; |
615 SlotsBuffer* slots_buffer_; | 620 SlotsBuffer* slots_buffer_; |
616 SkipList* skip_list_; | 621 SkipList* skip_list_; |
617 | 622 |
618 static MemoryChunk* Initialize(Heap* heap, | 623 static MemoryChunk* Initialize(Heap* heap, |
619 Address base, | 624 Address base, |
620 size_t size, | 625 size_t size, |
| 626 Address area_start, |
| 627 Address area_end, |
621 Executability executable, | 628 Executability executable, |
622 Space* owner); | 629 Space* owner); |
623 | 630 |
624 friend class MemoryAllocator; | 631 friend class MemoryAllocator; |
625 }; | 632 }; |
626 | 633 |
627 STATIC_CHECK(sizeof(MemoryChunk) <= MemoryChunk::kHeaderSize); | 634 STATIC_CHECK(sizeof(MemoryChunk) <= MemoryChunk::kHeaderSize); |
628 | 635 |
629 // ----------------------------------------------------------------------------- | 636 // ----------------------------------------------------------------------------- |
630 // A page is a memory chunk of a size 1MB. Large object pages may be larger. | 637 // A page is a memory chunk of a size 1MB. Large object pages may be larger. |
(...skipping 19 matching lines...) Expand all Loading... |
650 Page* p = FromAddress(top - kPointerSize); | 657 Page* p = FromAddress(top - kPointerSize); |
651 return p; | 658 return p; |
652 } | 659 } |
653 | 660 |
654 // Returns the next page in the chain of pages owned by a space. | 661 // Returns the next page in the chain of pages owned by a space. |
655 inline Page* next_page(); | 662 inline Page* next_page(); |
656 inline Page* prev_page(); | 663 inline Page* prev_page(); |
657 inline void set_next_page(Page* page); | 664 inline void set_next_page(Page* page); |
658 inline void set_prev_page(Page* page); | 665 inline void set_prev_page(Page* page); |
659 | 666 |
660 // Returns the start address of the object area in this page. | |
661 Address ObjectAreaStart() { return address() + kObjectStartOffset; } | |
662 | |
663 // Returns the end address (exclusive) of the object area in this page. | |
664 Address ObjectAreaEnd() { return address() + Page::kPageSize; } | |
665 | |
666 // Checks whether an address is page aligned. | 667 // Checks whether an address is page aligned. |
667 static bool IsAlignedToPageSize(Address a) { | 668 static bool IsAlignedToPageSize(Address a) { |
668 return 0 == (OffsetFrom(a) & kPageAlignmentMask); | 669 return 0 == (OffsetFrom(a) & kPageAlignmentMask); |
669 } | 670 } |
670 | 671 |
671 // Returns the offset of a given address to this page. | 672 // Returns the offset of a given address to this page. |
672 INLINE(int Offset(Address a)) { | 673 INLINE(int Offset(Address a)) { |
673 int offset = static_cast<int>(a - address()); | 674 int offset = static_cast<int>(a - address()); |
674 return offset; | 675 return offset; |
675 } | 676 } |
676 | 677 |
677 // Returns the address for a given offset to the this page. | 678 // Returns the address for a given offset to the this page. |
678 Address OffsetToAddress(int offset) { | 679 Address OffsetToAddress(int offset) { |
679 ASSERT_PAGE_OFFSET(offset); | 680 ASSERT_PAGE_OFFSET(offset); |
680 return address() + offset; | 681 return address() + offset; |
681 } | 682 } |
682 | 683 |
683 // --------------------------------------------------------------------- | 684 // --------------------------------------------------------------------- |
684 | 685 |
685 // Page size in bytes. This must be a multiple of the OS page size. | 686 // Page size in bytes. This must be a multiple of the OS page size. |
686 static const int kPageSize = 1 << kPageSizeBits; | 687 static const int kPageSize = 1 << kPageSizeBits; |
687 | 688 |
| 689 // Object area size in bytes. |
| 690 static const int kNonCodeObjectAreaSize = kPageSize - kObjectStartOffset; |
| 691 |
| 692 // Maximum object size that fits in a page. |
| 693 static const int kMaxNonCodeHeapObjectSize = kNonCodeObjectAreaSize; |
| 694 |
688 // Page size mask. | 695 // Page size mask. |
689 static const intptr_t kPageAlignmentMask = (1 << kPageSizeBits) - 1; | 696 static const intptr_t kPageAlignmentMask = (1 << kPageSizeBits) - 1; |
690 | 697 |
691 // Object area size in bytes. | |
692 static const int kObjectAreaSize = kPageSize - kObjectStartOffset; | |
693 | |
694 // Maximum object size that fits in a page. | |
695 static const int kMaxHeapObjectSize = kObjectAreaSize; | |
696 | |
697 static const int kFirstUsedCell = | |
698 (kObjectStartOffset/kPointerSize) >> Bitmap::kBitsPerCellLog2; | |
699 | |
700 static const int kLastUsedCell = | |
701 ((kPageSize - kPointerSize)/kPointerSize) >> | |
702 Bitmap::kBitsPerCellLog2; | |
703 | |
704 inline void ClearGCFields(); | 698 inline void ClearGCFields(); |
705 | 699 |
706 static inline Page* Initialize(Heap* heap, | 700 static inline Page* Initialize(Heap* heap, |
707 MemoryChunk* chunk, | 701 MemoryChunk* chunk, |
708 Executability executable, | 702 Executability executable, |
709 PagedSpace* owner); | 703 PagedSpace* owner); |
710 | 704 |
711 void InitializeAsAnchor(PagedSpace* owner); | 705 void InitializeAsAnchor(PagedSpace* owner); |
712 | 706 |
713 bool WasSweptPrecisely() { return IsFlagSet(WAS_SWEPT_PRECISELY); } | 707 bool WasSweptPrecisely() { return IsFlagSet(WAS_SWEPT_PRECISELY); } |
(...skipping 13 matching lines...) Expand all Loading... |
727 friend class MemoryAllocator; | 721 friend class MemoryAllocator; |
728 }; | 722 }; |
729 | 723 |
730 | 724 |
731 STATIC_CHECK(sizeof(Page) <= MemoryChunk::kHeaderSize); | 725 STATIC_CHECK(sizeof(Page) <= MemoryChunk::kHeaderSize); |
732 | 726 |
733 | 727 |
734 class LargePage : public MemoryChunk { | 728 class LargePage : public MemoryChunk { |
735 public: | 729 public: |
736 HeapObject* GetObject() { | 730 HeapObject* GetObject() { |
737 return HeapObject::FromAddress(body()); | 731 return HeapObject::FromAddress(area_start()); |
738 } | 732 } |
739 | 733 |
740 inline LargePage* next_page() const { | 734 inline LargePage* next_page() const { |
741 return static_cast<LargePage*>(next_chunk()); | 735 return static_cast<LargePage*>(next_chunk()); |
742 } | 736 } |
743 | 737 |
744 inline void set_next_page(LargePage* page) { | 738 inline void set_next_page(LargePage* page) { |
745 set_next_chunk(page); | 739 set_next_chunk(page); |
746 } | 740 } |
747 private: | 741 private: |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
968 intptr_t AvailableExecutable() { | 962 intptr_t AvailableExecutable() { |
969 if (capacity_executable_ < size_executable_) return 0; | 963 if (capacity_executable_ < size_executable_) return 0; |
970 return capacity_executable_ - size_executable_; | 964 return capacity_executable_ - size_executable_; |
971 } | 965 } |
972 | 966 |
973 // Returns allocated executable spaces in bytes. | 967 // Returns allocated executable spaces in bytes. |
974 intptr_t SizeExecutable() { return size_executable_; } | 968 intptr_t SizeExecutable() { return size_executable_; } |
975 | 969 |
976 // Returns maximum available bytes that the old space can have. | 970 // Returns maximum available bytes that the old space can have. |
977 intptr_t MaxAvailable() { | 971 intptr_t MaxAvailable() { |
978 return (Available() / Page::kPageSize) * Page::kObjectAreaSize; | 972 return (Available() / Page::kPageSize) * Page::kMaxNonCodeHeapObjectSize; |
979 } | 973 } |
980 | 974 |
981 #ifdef DEBUG | 975 #ifdef DEBUG |
982 // Reports statistic info of the space. | 976 // Reports statistic info of the space. |
983 void ReportStatistics(); | 977 void ReportStatistics(); |
984 #endif | 978 #endif |
985 | 979 |
986 MemoryChunk* AllocateChunk(intptr_t body_size, | 980 MemoryChunk* AllocateChunk(intptr_t body_size, |
987 Executability executable, | 981 Executability executable, |
988 Space* space); | 982 Space* space); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1021 void AddMemoryAllocationCallback(MemoryAllocationCallback callback, | 1015 void AddMemoryAllocationCallback(MemoryAllocationCallback callback, |
1022 ObjectSpace space, | 1016 ObjectSpace space, |
1023 AllocationAction action); | 1017 AllocationAction action); |
1024 | 1018 |
1025 void RemoveMemoryAllocationCallback( | 1019 void RemoveMemoryAllocationCallback( |
1026 MemoryAllocationCallback callback); | 1020 MemoryAllocationCallback callback); |
1027 | 1021 |
1028 bool MemoryAllocationCallbackRegistered( | 1022 bool MemoryAllocationCallbackRegistered( |
1029 MemoryAllocationCallback callback); | 1023 MemoryAllocationCallback callback); |
1030 | 1024 |
| 1025 static int CodePageGuardStartOffset(); |
| 1026 |
| 1027 static int CodePageGuardSize(); |
| 1028 |
| 1029 static int CodePageAreaStartOffset(); |
| 1030 |
| 1031 static int CodePageAreaEndOffset(); |
| 1032 |
| 1033 static int CodePageAreaSize() { |
| 1034 return CodePageAreaEndOffset() - CodePageAreaStartOffset(); |
| 1035 } |
| 1036 |
| 1037 static bool CommitCodePage(VirtualMemory* vm, Address start, size_t size); |
| 1038 |
1031 private: | 1039 private: |
1032 Isolate* isolate_; | 1040 Isolate* isolate_; |
1033 | 1041 |
1034 // Maximum space size in bytes. | 1042 // Maximum space size in bytes. |
1035 size_t capacity_; | 1043 size_t capacity_; |
1036 // Maximum subset of capacity_ that can be executable | 1044 // Maximum subset of capacity_ that can be executable |
1037 size_t capacity_executable_; | 1045 size_t capacity_executable_; |
1038 | 1046 |
1039 // Allocated space size in bytes. | 1047 // Allocated space size in bytes. |
1040 size_t size_; | 1048 size_t size_; |
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1373 intptr_t huge_size_; | 1381 intptr_t huge_size_; |
1374 }; | 1382 }; |
1375 | 1383 |
1376 void CountFreeListItems(Page* p, SizeStats* sizes); | 1384 void CountFreeListItems(Page* p, SizeStats* sizes); |
1377 | 1385 |
1378 intptr_t EvictFreeListItems(Page* p); | 1386 intptr_t EvictFreeListItems(Page* p); |
1379 | 1387 |
1380 private: | 1388 private: |
1381 // The size range of blocks, in bytes. | 1389 // The size range of blocks, in bytes. |
1382 static const int kMinBlockSize = 3 * kPointerSize; | 1390 static const int kMinBlockSize = 3 * kPointerSize; |
1383 static const int kMaxBlockSize = Page::kMaxHeapObjectSize; | 1391 static const int kMaxBlockSize = Page::kMaxNonCodeHeapObjectSize; |
1384 | 1392 |
1385 FreeListNode* PickNodeFromList(FreeListNode** list, int* node_size); | 1393 FreeListNode* PickNodeFromList(FreeListNode** list, int* node_size); |
1386 | 1394 |
1387 FreeListNode* FindNodeFor(int size_in_bytes, int* node_size); | 1395 FreeListNode* FindNodeFor(int size_in_bytes, int* node_size); |
1388 | 1396 |
1389 PagedSpace* owner_; | 1397 PagedSpace* owner_; |
1390 Heap* heap_; | 1398 Heap* heap_; |
1391 | 1399 |
1392 // Total available bytes in all blocks on this free list. | 1400 // Total available bytes in all blocks on this free list. |
1393 int available_; | 1401 int available_; |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1565 if (first == &anchor_) first = NULL; | 1573 if (first == &anchor_) first = NULL; |
1566 first_unswept_page_ = first; | 1574 first_unswept_page_ = first; |
1567 } | 1575 } |
1568 | 1576 |
1569 void IncrementUnsweptFreeBytes(int by) { | 1577 void IncrementUnsweptFreeBytes(int by) { |
1570 unswept_free_bytes_ += by; | 1578 unswept_free_bytes_ += by; |
1571 } | 1579 } |
1572 | 1580 |
1573 void IncreaseUnsweptFreeBytes(Page* p) { | 1581 void IncreaseUnsweptFreeBytes(Page* p) { |
1574 ASSERT(ShouldBeSweptLazily(p)); | 1582 ASSERT(ShouldBeSweptLazily(p)); |
1575 unswept_free_bytes_ += (Page::kObjectAreaSize - p->LiveBytes()); | 1583 unswept_free_bytes_ += (p->area_size() - p->LiveBytes()); |
1576 } | 1584 } |
1577 | 1585 |
1578 void DecreaseUnsweptFreeBytes(Page* p) { | 1586 void DecreaseUnsweptFreeBytes(Page* p) { |
1579 ASSERT(ShouldBeSweptLazily(p)); | 1587 ASSERT(ShouldBeSweptLazily(p)); |
1580 unswept_free_bytes_ -= (Page::kObjectAreaSize - p->LiveBytes()); | 1588 unswept_free_bytes_ -= (p->area_size() - p->LiveBytes()); |
1581 } | 1589 } |
1582 | 1590 |
1583 bool AdvanceSweeper(intptr_t bytes_to_sweep); | 1591 bool AdvanceSweeper(intptr_t bytes_to_sweep); |
1584 | 1592 |
1585 bool IsSweepingComplete() { | 1593 bool IsSweepingComplete() { |
1586 return !first_unswept_page_->is_valid(); | 1594 return !first_unswept_page_->is_valid(); |
1587 } | 1595 } |
1588 | 1596 |
1589 Page* FirstPage() { return anchor_.next_page(); } | 1597 Page* FirstPage() { return anchor_.next_page(); } |
1590 Page* LastPage() { return anchor_.prev_page(); } | 1598 Page* LastPage() { return anchor_.prev_page(); } |
1591 | 1599 |
1592 // Returns zero for pages that have so little fragmentation that it is not | 1600 // Returns zero for pages that have so little fragmentation that it is not |
1593 // worth defragmenting them. Otherwise a positive integer that gives an | 1601 // worth defragmenting them. Otherwise a positive integer that gives an |
1594 // estimate of fragmentation on an arbitrary scale. | 1602 // estimate of fragmentation on an arbitrary scale. |
1595 int Fragmentation(Page* p) { | 1603 int Fragmentation(Page* p) { |
1596 FreeList::SizeStats sizes; | 1604 FreeList::SizeStats sizes; |
1597 free_list_.CountFreeListItems(p, &sizes); | 1605 free_list_.CountFreeListItems(p, &sizes); |
1598 | 1606 |
1599 intptr_t ratio; | 1607 intptr_t ratio; |
1600 intptr_t ratio_threshold; | 1608 intptr_t ratio_threshold; |
1601 if (identity() == CODE_SPACE) { | 1609 if (identity() == CODE_SPACE) { |
1602 ratio = (sizes.medium_size_ * 10 + sizes.large_size_ * 2) * 100 / | 1610 ratio = (sizes.medium_size_ * 10 + sizes.large_size_ * 2) * 100 / |
1603 Page::kObjectAreaSize; | 1611 AreaSize(); |
1604 ratio_threshold = 10; | 1612 ratio_threshold = 10; |
1605 } else { | 1613 } else { |
1606 ratio = (sizes.small_size_ * 5 + sizes.medium_size_) * 100 / | 1614 ratio = (sizes.small_size_ * 5 + sizes.medium_size_) * 100 / |
1607 Page::kObjectAreaSize; | 1615 AreaSize(); |
1608 ratio_threshold = 15; | 1616 ratio_threshold = 15; |
1609 } | 1617 } |
1610 | 1618 |
1611 if (FLAG_trace_fragmentation) { | 1619 if (FLAG_trace_fragmentation) { |
1612 PrintF("%p [%d]: %d (%.2f%%) %d (%.2f%%) %d (%.2f%%) %d (%.2f%%) %s\n", | 1620 PrintF("%p [%d]: %d (%.2f%%) %d (%.2f%%) %d (%.2f%%) %d (%.2f%%) %s\n", |
1613 reinterpret_cast<void*>(p), | 1621 reinterpret_cast<void*>(p), |
1614 identity(), | 1622 identity(), |
1615 static_cast<int>(sizes.small_size_), | 1623 static_cast<int>(sizes.small_size_), |
1616 static_cast<double>(sizes.small_size_ * 100) / | 1624 static_cast<double>(sizes.small_size_ * 100) / |
1617 Page::kObjectAreaSize, | 1625 AreaSize(), |
1618 static_cast<int>(sizes.medium_size_), | 1626 static_cast<int>(sizes.medium_size_), |
1619 static_cast<double>(sizes.medium_size_ * 100) / | 1627 static_cast<double>(sizes.medium_size_ * 100) / |
1620 Page::kObjectAreaSize, | 1628 AreaSize(), |
1621 static_cast<int>(sizes.large_size_), | 1629 static_cast<int>(sizes.large_size_), |
1622 static_cast<double>(sizes.large_size_ * 100) / | 1630 static_cast<double>(sizes.large_size_ * 100) / |
1623 Page::kObjectAreaSize, | 1631 AreaSize(), |
1624 static_cast<int>(sizes.huge_size_), | 1632 static_cast<int>(sizes.huge_size_), |
1625 static_cast<double>(sizes.huge_size_ * 100) / | 1633 static_cast<double>(sizes.huge_size_ * 100) / |
1626 Page::kObjectAreaSize, | 1634 AreaSize(), |
1627 (ratio > ratio_threshold) ? "[fragmented]" : ""); | 1635 (ratio > ratio_threshold) ? "[fragmented]" : ""); |
1628 } | 1636 } |
1629 | 1637 |
1630 if (FLAG_always_compact && sizes.Total() != Page::kObjectAreaSize) { | 1638 if (FLAG_always_compact && sizes.Total() != AreaSize()) { |
1631 return 1; | 1639 return 1; |
1632 } | 1640 } |
1633 if (ratio <= ratio_threshold) return 0; // Not fragmented. | 1641 if (ratio <= ratio_threshold) return 0; // Not fragmented. |
1634 | 1642 |
1635 return static_cast<int>(ratio - ratio_threshold); | 1643 return static_cast<int>(ratio - ratio_threshold); |
1636 } | 1644 } |
1637 | 1645 |
1638 void EvictEvacuationCandidatesFromFreeLists(); | 1646 void EvictEvacuationCandidatesFromFreeLists(); |
1639 | 1647 |
1640 bool CanExpand(); | 1648 bool CanExpand(); |
1641 | 1649 |
1642 // Returns the number of total pages in this space. | 1650 // Returns the number of total pages in this space. |
1643 int CountTotalPages(); | 1651 int CountTotalPages(); |
1644 | 1652 |
| 1653 // Return size of allocatable area on a page in this space. |
| 1654 inline int AreaSize() { |
| 1655 return area_size_; |
| 1656 } |
| 1657 |
1645 protected: | 1658 protected: |
| 1659 int area_size_; |
| 1660 |
1646 // Maximum capacity of this space. | 1661 // Maximum capacity of this space. |
1647 intptr_t max_capacity_; | 1662 intptr_t max_capacity_; |
1648 | 1663 |
1649 // Accounting information for this space. | 1664 // Accounting information for this space. |
1650 AllocationStats accounting_stats_; | 1665 AllocationStats accounting_stats_; |
1651 | 1666 |
1652 // The dummy page that anchors the double linked list of pages. | 1667 // The dummy page that anchors the double linked list of pages. |
1653 Page anchor_; | 1668 Page anchor_; |
1654 | 1669 |
1655 // The space's free list. | 1670 // The space's free list. |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1737 | 1752 |
1738 class NewSpacePage : public MemoryChunk { | 1753 class NewSpacePage : public MemoryChunk { |
1739 public: | 1754 public: |
1740 // GC related flags copied from from-space to to-space when | 1755 // GC related flags copied from from-space to to-space when |
1741 // flipping semispaces. | 1756 // flipping semispaces. |
1742 static const intptr_t kCopyOnFlipFlagsMask = | 1757 static const intptr_t kCopyOnFlipFlagsMask = |
1743 (1 << MemoryChunk::POINTERS_TO_HERE_ARE_INTERESTING) | | 1758 (1 << MemoryChunk::POINTERS_TO_HERE_ARE_INTERESTING) | |
1744 (1 << MemoryChunk::POINTERS_FROM_HERE_ARE_INTERESTING) | | 1759 (1 << MemoryChunk::POINTERS_FROM_HERE_ARE_INTERESTING) | |
1745 (1 << MemoryChunk::SCAN_ON_SCAVENGE); | 1760 (1 << MemoryChunk::SCAN_ON_SCAVENGE); |
1746 | 1761 |
| 1762 static const int kAreaSize = Page::kNonCodeObjectAreaSize; |
| 1763 |
1747 inline NewSpacePage* next_page() const { | 1764 inline NewSpacePage* next_page() const { |
1748 return static_cast<NewSpacePage*>(next_chunk()); | 1765 return static_cast<NewSpacePage*>(next_chunk()); |
1749 } | 1766 } |
1750 | 1767 |
1751 inline void set_next_page(NewSpacePage* page) { | 1768 inline void set_next_page(NewSpacePage* page) { |
1752 set_next_chunk(page); | 1769 set_next_chunk(page); |
1753 } | 1770 } |
1754 | 1771 |
1755 inline NewSpacePage* prev_page() const { | 1772 inline NewSpacePage* prev_page() const { |
1756 return static_cast<NewSpacePage*>(prev_chunk()); | 1773 return static_cast<NewSpacePage*>(prev_chunk()); |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1849 bool GrowTo(int new_capacity); | 1866 bool GrowTo(int new_capacity); |
1850 | 1867 |
1851 // Shrinks the semispace to the new capacity. The new capacity | 1868 // Shrinks the semispace to the new capacity. The new capacity |
1852 // requested must be more than the amount of used memory in the | 1869 // requested must be more than the amount of used memory in the |
1853 // semispace and less than the current capacity. | 1870 // semispace and less than the current capacity. |
1854 bool ShrinkTo(int new_capacity); | 1871 bool ShrinkTo(int new_capacity); |
1855 | 1872 |
1856 // Returns the start address of the first page of the space. | 1873 // Returns the start address of the first page of the space. |
1857 Address space_start() { | 1874 Address space_start() { |
1858 ASSERT(anchor_.next_page() != &anchor_); | 1875 ASSERT(anchor_.next_page() != &anchor_); |
1859 return anchor_.next_page()->body(); | 1876 return anchor_.next_page()->area_start(); |
1860 } | 1877 } |
1861 | 1878 |
1862 // Returns the start address of the current page of the space. | 1879 // Returns the start address of the current page of the space. |
1863 Address page_low() { | 1880 Address page_low() { |
1864 return current_page_->body(); | 1881 return current_page_->area_start(); |
1865 } | 1882 } |
1866 | 1883 |
1867 // Returns one past the end address of the space. | 1884 // Returns one past the end address of the space. |
1868 Address space_end() { | 1885 Address space_end() { |
1869 return anchor_.prev_page()->body_limit(); | 1886 return anchor_.prev_page()->area_end(); |
1870 } | 1887 } |
1871 | 1888 |
1872 // Returns one past the end address of the current page of the space. | 1889 // Returns one past the end address of the current page of the space. |
1873 Address page_high() { | 1890 Address page_high() { |
1874 return current_page_->body_limit(); | 1891 return current_page_->area_end(); |
1875 } | 1892 } |
1876 | 1893 |
1877 bool AdvancePage() { | 1894 bool AdvancePage() { |
1878 NewSpacePage* next_page = current_page_->next_page(); | 1895 NewSpacePage* next_page = current_page_->next_page(); |
1879 if (next_page == anchor()) return false; | 1896 if (next_page == anchor()) return false; |
1880 current_page_ = next_page; | 1897 current_page_ = next_page; |
1881 return true; | 1898 return true; |
1882 } | 1899 } |
1883 | 1900 |
1884 // Resets the space to using the first page. | 1901 // Resets the space to using the first page. |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2000 SemiSpaceIterator(NewSpace* space, Address start); | 2017 SemiSpaceIterator(NewSpace* space, Address start); |
2001 // Iterate from one address to another in the same semi-space. | 2018 // Iterate from one address to another in the same semi-space. |
2002 SemiSpaceIterator(Address from, Address to); | 2019 SemiSpaceIterator(Address from, Address to); |
2003 | 2020 |
2004 HeapObject* Next() { | 2021 HeapObject* Next() { |
2005 if (current_ == limit_) return NULL; | 2022 if (current_ == limit_) return NULL; |
2006 if (NewSpacePage::IsAtEnd(current_)) { | 2023 if (NewSpacePage::IsAtEnd(current_)) { |
2007 NewSpacePage* page = NewSpacePage::FromLimit(current_); | 2024 NewSpacePage* page = NewSpacePage::FromLimit(current_); |
2008 page = page->next_page(); | 2025 page = page->next_page(); |
2009 ASSERT(!page->is_anchor()); | 2026 ASSERT(!page->is_anchor()); |
2010 current_ = page->body(); | 2027 current_ = page->area_start(); |
2011 if (current_ == limit_) return NULL; | 2028 if (current_ == limit_) return NULL; |
2012 } | 2029 } |
2013 | 2030 |
2014 HeapObject* object = HeapObject::FromAddress(current_); | 2031 HeapObject* object = HeapObject::FromAddress(current_); |
2015 int size = (size_func_ == NULL) ? object->Size() : size_func_(object); | 2032 int size = (size_func_ == NULL) ? object->Size() : size_func_(object); |
2016 | 2033 |
2017 current_ += size; | 2034 current_ += size; |
2018 return object; | 2035 return object; |
2019 } | 2036 } |
2020 | 2037 |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2108 == reinterpret_cast<uintptr_t>(start_); | 2125 == reinterpret_cast<uintptr_t>(start_); |
2109 } | 2126 } |
2110 | 2127 |
2111 bool Contains(Object* o) { | 2128 bool Contains(Object* o) { |
2112 Address a = reinterpret_cast<Address>(o); | 2129 Address a = reinterpret_cast<Address>(o); |
2113 return (reinterpret_cast<uintptr_t>(a) & object_mask_) == object_expected_; | 2130 return (reinterpret_cast<uintptr_t>(a) & object_mask_) == object_expected_; |
2114 } | 2131 } |
2115 | 2132 |
2116 // Return the allocated bytes in the active semispace. | 2133 // Return the allocated bytes in the active semispace. |
2117 virtual intptr_t Size() { | 2134 virtual intptr_t Size() { |
2118 return pages_used_ * Page::kObjectAreaSize + | 2135 return pages_used_ * NewSpacePage::kAreaSize + |
2119 static_cast<int>(top() - to_space_.page_low()); | 2136 static_cast<int>(top() - to_space_.page_low()); |
2120 } | 2137 } |
2121 | 2138 |
2122 // The same, but returning an int. We have to have the one that returns | 2139 // The same, but returning an int. We have to have the one that returns |
2123 // intptr_t because it is inherited, but if we know we are dealing with the | 2140 // intptr_t because it is inherited, but if we know we are dealing with the |
2124 // new space, which can't get as big as the other spaces then this is useful: | 2141 // new space, which can't get as big as the other spaces then this is useful: |
2125 int SizeAsInt() { return static_cast<int>(Size()); } | 2142 int SizeAsInt() { return static_cast<int>(Size()); } |
2126 | 2143 |
2127 // Return the current capacity of a semispace. | 2144 // Return the current capacity of a semispace. |
2128 intptr_t EffectiveCapacity() { | 2145 intptr_t EffectiveCapacity() { |
2129 SLOW_ASSERT(to_space_.Capacity() == from_space_.Capacity()); | 2146 SLOW_ASSERT(to_space_.Capacity() == from_space_.Capacity()); |
2130 return (to_space_.Capacity() / Page::kPageSize) * Page::kObjectAreaSize; | 2147 return (to_space_.Capacity() / Page::kPageSize) * NewSpacePage::kAreaSize; |
2131 } | 2148 } |
2132 | 2149 |
2133 // Return the current capacity of a semispace. | 2150 // Return the current capacity of a semispace. |
2134 intptr_t Capacity() { | 2151 intptr_t Capacity() { |
2135 ASSERT(to_space_.Capacity() == from_space_.Capacity()); | 2152 ASSERT(to_space_.Capacity() == from_space_.Capacity()); |
2136 return to_space_.Capacity(); | 2153 return to_space_.Capacity(); |
2137 } | 2154 } |
2138 | 2155 |
2139 // Return the total amount of memory committed for new space. | 2156 // Return the total amount of memory committed for new space. |
2140 intptr_t CommittedMemory() { | 2157 intptr_t CommittedMemory() { |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2337 OldSpace(Heap* heap, | 2354 OldSpace(Heap* heap, |
2338 intptr_t max_capacity, | 2355 intptr_t max_capacity, |
2339 AllocationSpace id, | 2356 AllocationSpace id, |
2340 Executability executable) | 2357 Executability executable) |
2341 : PagedSpace(heap, max_capacity, id, executable) { | 2358 : PagedSpace(heap, max_capacity, id, executable) { |
2342 page_extra_ = 0; | 2359 page_extra_ = 0; |
2343 } | 2360 } |
2344 | 2361 |
2345 // The limit of allocation for a page in this space. | 2362 // The limit of allocation for a page in this space. |
2346 virtual Address PageAllocationLimit(Page* page) { | 2363 virtual Address PageAllocationLimit(Page* page) { |
2347 return page->ObjectAreaEnd(); | 2364 return page->area_end(); |
2348 } | 2365 } |
2349 | 2366 |
2350 public: | 2367 public: |
2351 TRACK_MEMORY("OldSpace") | 2368 TRACK_MEMORY("OldSpace") |
2352 }; | 2369 }; |
2353 | 2370 |
2354 | 2371 |
2355 // For contiguous spaces, top should be in the space (or at the end) and limit | 2372 // For contiguous spaces, top should be in the space (or at the end) and limit |
2356 // should be the end of the space. | 2373 // should be the end of the space. |
2357 #define ASSERT_SEMISPACE_ALLOCATION_INFO(info, space) \ | 2374 #define ASSERT_SEMISPACE_ALLOCATION_INFO(info, space) \ |
2358 SLOW_ASSERT((space).page_low() <= (info).top \ | 2375 SLOW_ASSERT((space).page_low() <= (info).top \ |
2359 && (info).top <= (space).page_high() \ | 2376 && (info).top <= (space).page_high() \ |
2360 && (info).limit <= (space).page_high()) | 2377 && (info).limit <= (space).page_high()) |
2361 | 2378 |
2362 | 2379 |
2363 // ----------------------------------------------------------------------------- | 2380 // ----------------------------------------------------------------------------- |
2364 // Old space for objects of a fixed size | 2381 // Old space for objects of a fixed size |
2365 | 2382 |
2366 class FixedSpace : public PagedSpace { | 2383 class FixedSpace : public PagedSpace { |
2367 public: | 2384 public: |
2368 FixedSpace(Heap* heap, | 2385 FixedSpace(Heap* heap, |
2369 intptr_t max_capacity, | 2386 intptr_t max_capacity, |
2370 AllocationSpace id, | 2387 AllocationSpace id, |
2371 int object_size_in_bytes, | 2388 int object_size_in_bytes, |
2372 const char* name) | 2389 const char* name) |
2373 : PagedSpace(heap, max_capacity, id, NOT_EXECUTABLE), | 2390 : PagedSpace(heap, max_capacity, id, NOT_EXECUTABLE), |
2374 object_size_in_bytes_(object_size_in_bytes), | 2391 object_size_in_bytes_(object_size_in_bytes), |
2375 name_(name) { | 2392 name_(name) { |
2376 page_extra_ = Page::kObjectAreaSize % object_size_in_bytes; | 2393 page_extra_ = Page::kNonCodeObjectAreaSize % object_size_in_bytes; |
2377 } | 2394 } |
2378 | 2395 |
2379 // The limit of allocation for a page in this space. | 2396 // The limit of allocation for a page in this space. |
2380 virtual Address PageAllocationLimit(Page* page) { | 2397 virtual Address PageAllocationLimit(Page* page) { |
2381 return page->ObjectAreaEnd() - page_extra_; | 2398 return page->area_end() - page_extra_; |
2382 } | 2399 } |
2383 | 2400 |
2384 int object_size_in_bytes() { return object_size_in_bytes_; } | 2401 int object_size_in_bytes() { return object_size_in_bytes_; } |
2385 | 2402 |
2386 // Prepares for a mark-compact GC. | 2403 // Prepares for a mark-compact GC. |
2387 virtual void PrepareForMarkCompact(); | 2404 virtual void PrepareForMarkCompact(); |
2388 | 2405 |
2389 protected: | 2406 protected: |
2390 void ResetFreeList() { | 2407 void ResetFreeList() { |
2391 free_list_.Reset(); | 2408 free_list_.Reset(); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2425 return (size / Map::kSize) * Map::kSize; | 2442 return (size / Map::kSize) * Map::kSize; |
2426 } | 2443 } |
2427 } | 2444 } |
2428 | 2445 |
2429 protected: | 2446 protected: |
2430 #ifdef DEBUG | 2447 #ifdef DEBUG |
2431 virtual void VerifyObject(HeapObject* obj); | 2448 virtual void VerifyObject(HeapObject* obj); |
2432 #endif | 2449 #endif |
2433 | 2450 |
2434 private: | 2451 private: |
2435 static const int kMapsPerPage = Page::kObjectAreaSize / Map::kSize; | 2452 static const int kMapsPerPage = Page::kNonCodeObjectAreaSize / Map::kSize; |
2436 | 2453 |
2437 // Do map space compaction if there is a page gap. | 2454 // Do map space compaction if there is a page gap. |
2438 int CompactionThreshold() { | 2455 int CompactionThreshold() { |
2439 return kMapsPerPage * (max_map_space_pages_ - 1); | 2456 return kMapsPerPage * (max_map_space_pages_ - 1); |
2440 } | 2457 } |
2441 | 2458 |
2442 const int max_map_space_pages_; | 2459 const int max_map_space_pages_; |
2443 | 2460 |
2444 public: | 2461 public: |
2445 TRACK_MEMORY("MapSpace") | 2462 TRACK_MEMORY("MapSpace") |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2656 } | 2673 } |
2657 // Must be small, since an iteration is used for lookup. | 2674 // Must be small, since an iteration is used for lookup. |
2658 static const int kMaxComments = 64; | 2675 static const int kMaxComments = 64; |
2659 }; | 2676 }; |
2660 #endif | 2677 #endif |
2661 | 2678 |
2662 | 2679 |
2663 } } // namespace v8::internal | 2680 } } // namespace v8::internal |
2664 | 2681 |
2665 #endif // V8_SPACES_H_ | 2682 #endif // V8_SPACES_H_ |
OLD | NEW |