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 void CountFreeListItems(Page* p, FreeList::SizeStats* sizes) { | 1600 void CountFreeListItems(Page* p, FreeList::SizeStats* sizes) { |
1593 free_list_.CountFreeListItems(p, sizes); | 1601 free_list_.CountFreeListItems(p, sizes); |
1594 } | 1602 } |
1595 | 1603 |
1596 void EvictEvacuationCandidatesFromFreeLists(); | 1604 void EvictEvacuationCandidatesFromFreeLists(); |
1597 | 1605 |
1598 bool CanExpand(); | 1606 bool CanExpand(); |
1599 | 1607 |
1600 // Returns the number of total pages in this space. | 1608 // Returns the number of total pages in this space. |
1601 int CountTotalPages(); | 1609 int CountTotalPages(); |
1602 | 1610 |
| 1611 // Return size of allocatable area on a page in this space. |
| 1612 inline int AreaSize() { |
| 1613 return area_size_; |
| 1614 } |
| 1615 |
1603 protected: | 1616 protected: |
| 1617 int area_size_; |
| 1618 |
1604 // Maximum capacity of this space. | 1619 // Maximum capacity of this space. |
1605 intptr_t max_capacity_; | 1620 intptr_t max_capacity_; |
1606 | 1621 |
1607 // Accounting information for this space. | 1622 // Accounting information for this space. |
1608 AllocationStats accounting_stats_; | 1623 AllocationStats accounting_stats_; |
1609 | 1624 |
1610 // The dummy page that anchors the double linked list of pages. | 1625 // The dummy page that anchors the double linked list of pages. |
1611 Page anchor_; | 1626 Page anchor_; |
1612 | 1627 |
1613 // The space's free list. | 1628 // The space's free list. |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1695 | 1710 |
1696 class NewSpacePage : public MemoryChunk { | 1711 class NewSpacePage : public MemoryChunk { |
1697 public: | 1712 public: |
1698 // GC related flags copied from from-space to to-space when | 1713 // GC related flags copied from from-space to to-space when |
1699 // flipping semispaces. | 1714 // flipping semispaces. |
1700 static const intptr_t kCopyOnFlipFlagsMask = | 1715 static const intptr_t kCopyOnFlipFlagsMask = |
1701 (1 << MemoryChunk::POINTERS_TO_HERE_ARE_INTERESTING) | | 1716 (1 << MemoryChunk::POINTERS_TO_HERE_ARE_INTERESTING) | |
1702 (1 << MemoryChunk::POINTERS_FROM_HERE_ARE_INTERESTING) | | 1717 (1 << MemoryChunk::POINTERS_FROM_HERE_ARE_INTERESTING) | |
1703 (1 << MemoryChunk::SCAN_ON_SCAVENGE); | 1718 (1 << MemoryChunk::SCAN_ON_SCAVENGE); |
1704 | 1719 |
| 1720 static const int kAreaSize = Page::kNonCodeObjectAreaSize; |
| 1721 |
1705 inline NewSpacePage* next_page() const { | 1722 inline NewSpacePage* next_page() const { |
1706 return static_cast<NewSpacePage*>(next_chunk()); | 1723 return static_cast<NewSpacePage*>(next_chunk()); |
1707 } | 1724 } |
1708 | 1725 |
1709 inline void set_next_page(NewSpacePage* page) { | 1726 inline void set_next_page(NewSpacePage* page) { |
1710 set_next_chunk(page); | 1727 set_next_chunk(page); |
1711 } | 1728 } |
1712 | 1729 |
1713 inline NewSpacePage* prev_page() const { | 1730 inline NewSpacePage* prev_page() const { |
1714 return static_cast<NewSpacePage*>(prev_chunk()); | 1731 return static_cast<NewSpacePage*>(prev_chunk()); |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1807 bool GrowTo(int new_capacity); | 1824 bool GrowTo(int new_capacity); |
1808 | 1825 |
1809 // Shrinks the semispace to the new capacity. The new capacity | 1826 // Shrinks the semispace to the new capacity. The new capacity |
1810 // requested must be more than the amount of used memory in the | 1827 // requested must be more than the amount of used memory in the |
1811 // semispace and less than the current capacity. | 1828 // semispace and less than the current capacity. |
1812 bool ShrinkTo(int new_capacity); | 1829 bool ShrinkTo(int new_capacity); |
1813 | 1830 |
1814 // Returns the start address of the first page of the space. | 1831 // Returns the start address of the first page of the space. |
1815 Address space_start() { | 1832 Address space_start() { |
1816 ASSERT(anchor_.next_page() != &anchor_); | 1833 ASSERT(anchor_.next_page() != &anchor_); |
1817 return anchor_.next_page()->body(); | 1834 return anchor_.next_page()->area_start(); |
1818 } | 1835 } |
1819 | 1836 |
1820 // Returns the start address of the current page of the space. | 1837 // Returns the start address of the current page of the space. |
1821 Address page_low() { | 1838 Address page_low() { |
1822 return current_page_->body(); | 1839 return current_page_->area_start(); |
1823 } | 1840 } |
1824 | 1841 |
1825 // Returns one past the end address of the space. | 1842 // Returns one past the end address of the space. |
1826 Address space_end() { | 1843 Address space_end() { |
1827 return anchor_.prev_page()->body_limit(); | 1844 return anchor_.prev_page()->area_end(); |
1828 } | 1845 } |
1829 | 1846 |
1830 // Returns one past the end address of the current page of the space. | 1847 // Returns one past the end address of the current page of the space. |
1831 Address page_high() { | 1848 Address page_high() { |
1832 return current_page_->body_limit(); | 1849 return current_page_->area_end(); |
1833 } | 1850 } |
1834 | 1851 |
1835 bool AdvancePage() { | 1852 bool AdvancePage() { |
1836 NewSpacePage* next_page = current_page_->next_page(); | 1853 NewSpacePage* next_page = current_page_->next_page(); |
1837 if (next_page == anchor()) return false; | 1854 if (next_page == anchor()) return false; |
1838 current_page_ = next_page; | 1855 current_page_ = next_page; |
1839 return true; | 1856 return true; |
1840 } | 1857 } |
1841 | 1858 |
1842 // Resets the space to using the first page. | 1859 // Resets the space to using the first page. |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1958 SemiSpaceIterator(NewSpace* space, Address start); | 1975 SemiSpaceIterator(NewSpace* space, Address start); |
1959 // Iterate from one address to another in the same semi-space. | 1976 // Iterate from one address to another in the same semi-space. |
1960 SemiSpaceIterator(Address from, Address to); | 1977 SemiSpaceIterator(Address from, Address to); |
1961 | 1978 |
1962 HeapObject* Next() { | 1979 HeapObject* Next() { |
1963 if (current_ == limit_) return NULL; | 1980 if (current_ == limit_) return NULL; |
1964 if (NewSpacePage::IsAtEnd(current_)) { | 1981 if (NewSpacePage::IsAtEnd(current_)) { |
1965 NewSpacePage* page = NewSpacePage::FromLimit(current_); | 1982 NewSpacePage* page = NewSpacePage::FromLimit(current_); |
1966 page = page->next_page(); | 1983 page = page->next_page(); |
1967 ASSERT(!page->is_anchor()); | 1984 ASSERT(!page->is_anchor()); |
1968 current_ = page->body(); | 1985 current_ = page->area_start(); |
1969 if (current_ == limit_) return NULL; | 1986 if (current_ == limit_) return NULL; |
1970 } | 1987 } |
1971 | 1988 |
1972 HeapObject* object = HeapObject::FromAddress(current_); | 1989 HeapObject* object = HeapObject::FromAddress(current_); |
1973 int size = (size_func_ == NULL) ? object->Size() : size_func_(object); | 1990 int size = (size_func_ == NULL) ? object->Size() : size_func_(object); |
1974 | 1991 |
1975 current_ += size; | 1992 current_ += size; |
1976 return object; | 1993 return object; |
1977 } | 1994 } |
1978 | 1995 |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2066 == reinterpret_cast<uintptr_t>(start_); | 2083 == reinterpret_cast<uintptr_t>(start_); |
2067 } | 2084 } |
2068 | 2085 |
2069 bool Contains(Object* o) { | 2086 bool Contains(Object* o) { |
2070 Address a = reinterpret_cast<Address>(o); | 2087 Address a = reinterpret_cast<Address>(o); |
2071 return (reinterpret_cast<uintptr_t>(a) & object_mask_) == object_expected_; | 2088 return (reinterpret_cast<uintptr_t>(a) & object_mask_) == object_expected_; |
2072 } | 2089 } |
2073 | 2090 |
2074 // Return the allocated bytes in the active semispace. | 2091 // Return the allocated bytes in the active semispace. |
2075 virtual intptr_t Size() { | 2092 virtual intptr_t Size() { |
2076 return pages_used_ * Page::kObjectAreaSize + | 2093 return pages_used_ * NewSpacePage::kAreaSize + |
2077 static_cast<int>(top() - to_space_.page_low()); | 2094 static_cast<int>(top() - to_space_.page_low()); |
2078 } | 2095 } |
2079 | 2096 |
2080 // The same, but returning an int. We have to have the one that returns | 2097 // The same, but returning an int. We have to have the one that returns |
2081 // intptr_t because it is inherited, but if we know we are dealing with the | 2098 // intptr_t because it is inherited, but if we know we are dealing with the |
2082 // new space, which can't get as big as the other spaces then this is useful: | 2099 // new space, which can't get as big as the other spaces then this is useful: |
2083 int SizeAsInt() { return static_cast<int>(Size()); } | 2100 int SizeAsInt() { return static_cast<int>(Size()); } |
2084 | 2101 |
2085 // Return the current capacity of a semispace. | 2102 // Return the current capacity of a semispace. |
2086 intptr_t EffectiveCapacity() { | 2103 intptr_t EffectiveCapacity() { |
2087 SLOW_ASSERT(to_space_.Capacity() == from_space_.Capacity()); | 2104 SLOW_ASSERT(to_space_.Capacity() == from_space_.Capacity()); |
2088 return (to_space_.Capacity() / Page::kPageSize) * Page::kObjectAreaSize; | 2105 return (to_space_.Capacity() / Page::kPageSize) * NewSpacePage::kAreaSize; |
2089 } | 2106 } |
2090 | 2107 |
2091 // Return the current capacity of a semispace. | 2108 // Return the current capacity of a semispace. |
2092 intptr_t Capacity() { | 2109 intptr_t Capacity() { |
2093 ASSERT(to_space_.Capacity() == from_space_.Capacity()); | 2110 ASSERT(to_space_.Capacity() == from_space_.Capacity()); |
2094 return to_space_.Capacity(); | 2111 return to_space_.Capacity(); |
2095 } | 2112 } |
2096 | 2113 |
2097 // Return the total amount of memory committed for new space. | 2114 // Return the total amount of memory committed for new space. |
2098 intptr_t CommittedMemory() { | 2115 intptr_t CommittedMemory() { |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2295 OldSpace(Heap* heap, | 2312 OldSpace(Heap* heap, |
2296 intptr_t max_capacity, | 2313 intptr_t max_capacity, |
2297 AllocationSpace id, | 2314 AllocationSpace id, |
2298 Executability executable) | 2315 Executability executable) |
2299 : PagedSpace(heap, max_capacity, id, executable) { | 2316 : PagedSpace(heap, max_capacity, id, executable) { |
2300 page_extra_ = 0; | 2317 page_extra_ = 0; |
2301 } | 2318 } |
2302 | 2319 |
2303 // The limit of allocation for a page in this space. | 2320 // The limit of allocation for a page in this space. |
2304 virtual Address PageAllocationLimit(Page* page) { | 2321 virtual Address PageAllocationLimit(Page* page) { |
2305 return page->ObjectAreaEnd(); | 2322 return page->area_end(); |
2306 } | 2323 } |
2307 | 2324 |
2308 public: | 2325 public: |
2309 TRACK_MEMORY("OldSpace") | 2326 TRACK_MEMORY("OldSpace") |
2310 }; | 2327 }; |
2311 | 2328 |
2312 | 2329 |
2313 // For contiguous spaces, top should be in the space (or at the end) and limit | 2330 // For contiguous spaces, top should be in the space (or at the end) and limit |
2314 // should be the end of the space. | 2331 // should be the end of the space. |
2315 #define ASSERT_SEMISPACE_ALLOCATION_INFO(info, space) \ | 2332 #define ASSERT_SEMISPACE_ALLOCATION_INFO(info, space) \ |
2316 SLOW_ASSERT((space).page_low() <= (info).top \ | 2333 SLOW_ASSERT((space).page_low() <= (info).top \ |
2317 && (info).top <= (space).page_high() \ | 2334 && (info).top <= (space).page_high() \ |
2318 && (info).limit <= (space).page_high()) | 2335 && (info).limit <= (space).page_high()) |
2319 | 2336 |
2320 | 2337 |
2321 // ----------------------------------------------------------------------------- | 2338 // ----------------------------------------------------------------------------- |
2322 // Old space for objects of a fixed size | 2339 // Old space for objects of a fixed size |
2323 | 2340 |
2324 class FixedSpace : public PagedSpace { | 2341 class FixedSpace : public PagedSpace { |
2325 public: | 2342 public: |
2326 FixedSpace(Heap* heap, | 2343 FixedSpace(Heap* heap, |
2327 intptr_t max_capacity, | 2344 intptr_t max_capacity, |
2328 AllocationSpace id, | 2345 AllocationSpace id, |
2329 int object_size_in_bytes, | 2346 int object_size_in_bytes, |
2330 const char* name) | 2347 const char* name) |
2331 : PagedSpace(heap, max_capacity, id, NOT_EXECUTABLE), | 2348 : PagedSpace(heap, max_capacity, id, NOT_EXECUTABLE), |
2332 object_size_in_bytes_(object_size_in_bytes), | 2349 object_size_in_bytes_(object_size_in_bytes), |
2333 name_(name) { | 2350 name_(name) { |
2334 page_extra_ = Page::kObjectAreaSize % object_size_in_bytes; | 2351 page_extra_ = Page::kNonCodeObjectAreaSize % object_size_in_bytes; |
2335 } | 2352 } |
2336 | 2353 |
2337 // The limit of allocation for a page in this space. | 2354 // The limit of allocation for a page in this space. |
2338 virtual Address PageAllocationLimit(Page* page) { | 2355 virtual Address PageAllocationLimit(Page* page) { |
2339 return page->ObjectAreaEnd() - page_extra_; | 2356 return page->area_end() - page_extra_; |
2340 } | 2357 } |
2341 | 2358 |
2342 int object_size_in_bytes() { return object_size_in_bytes_; } | 2359 int object_size_in_bytes() { return object_size_in_bytes_; } |
2343 | 2360 |
2344 // Prepares for a mark-compact GC. | 2361 // Prepares for a mark-compact GC. |
2345 virtual void PrepareForMarkCompact(); | 2362 virtual void PrepareForMarkCompact(); |
2346 | 2363 |
2347 protected: | 2364 protected: |
2348 void ResetFreeList() { | 2365 void ResetFreeList() { |
2349 free_list_.Reset(); | 2366 free_list_.Reset(); |
(...skipping 30 matching lines...) Expand all Loading... |
2380 return (size / Map::kSize) * Map::kSize; | 2397 return (size / Map::kSize) * Map::kSize; |
2381 } | 2398 } |
2382 } | 2399 } |
2383 | 2400 |
2384 protected: | 2401 protected: |
2385 #ifdef DEBUG | 2402 #ifdef DEBUG |
2386 virtual void VerifyObject(HeapObject* obj); | 2403 virtual void VerifyObject(HeapObject* obj); |
2387 #endif | 2404 #endif |
2388 | 2405 |
2389 private: | 2406 private: |
2390 static const int kMapsPerPage = Page::kObjectAreaSize / Map::kSize; | 2407 static const int kMapsPerPage = Page::kNonCodeObjectAreaSize / Map::kSize; |
2391 | 2408 |
2392 // Do map space compaction if there is a page gap. | 2409 // Do map space compaction if there is a page gap. |
2393 int CompactionThreshold() { | 2410 int CompactionThreshold() { |
2394 return kMapsPerPage * (max_map_space_pages_ - 1); | 2411 return kMapsPerPage * (max_map_space_pages_ - 1); |
2395 } | 2412 } |
2396 | 2413 |
2397 const int max_map_space_pages_; | 2414 const int max_map_space_pages_; |
2398 | 2415 |
2399 public: | 2416 public: |
2400 TRACK_MEMORY("MapSpace") | 2417 TRACK_MEMORY("MapSpace") |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2611 } | 2628 } |
2612 // Must be small, since an iteration is used for lookup. | 2629 // Must be small, since an iteration is used for lookup. |
2613 static const int kMaxComments = 64; | 2630 static const int kMaxComments = 64; |
2614 }; | 2631 }; |
2615 #endif | 2632 #endif |
2616 | 2633 |
2617 | 2634 |
2618 } } // namespace v8::internal | 2635 } } // namespace v8::internal |
2619 | 2636 |
2620 #endif // V8_SPACES_H_ | 2637 #endif // V8_SPACES_H_ |
OLD | NEW |