| 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 |