| 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 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 385 WAS_SWEPT_CONSERVATIVELY, | 385 WAS_SWEPT_CONSERVATIVELY, |
| 386 ABOUT_TO_BE_FREED, | 386 ABOUT_TO_BE_FREED, |
| 387 POINTERS_TO_HERE_ARE_INTERESTING, | 387 POINTERS_TO_HERE_ARE_INTERESTING, |
| 388 POINTERS_FROM_HERE_ARE_INTERESTING, | 388 POINTERS_FROM_HERE_ARE_INTERESTING, |
| 389 SCAN_ON_SCAVENGE, | 389 SCAN_ON_SCAVENGE, |
| 390 IN_FROM_SPACE, // Mutually exclusive with IN_TO_SPACE. | 390 IN_FROM_SPACE, // Mutually exclusive with IN_TO_SPACE. |
| 391 IN_TO_SPACE, // All pages in new space has one of these two set. | 391 IN_TO_SPACE, // All pages in new space has one of these two set. |
| 392 NEW_SPACE_BELOW_AGE_MARK, | 392 NEW_SPACE_BELOW_AGE_MARK, |
| 393 CONTAINS_ONLY_DATA, | 393 CONTAINS_ONLY_DATA, |
| 394 EVACUATION_CANDIDATE, | 394 EVACUATION_CANDIDATE, |
| 395 EVACUATED, |
| 395 NUM_MEMORY_CHUNK_FLAGS | 396 NUM_MEMORY_CHUNK_FLAGS |
| 396 }; | 397 }; |
| 397 | 398 |
| 399 |
| 400 static const int kPointersToHereAreInterestingMask = |
| 401 1 << POINTERS_TO_HERE_ARE_INTERESTING; |
| 402 |
| 403 static const int kPointersFromHereAreInterestingMask = |
| 404 1 << POINTERS_FROM_HERE_ARE_INTERESTING; |
| 405 |
| 406 static const int kEvacuationCandidateMask = |
| 407 1 << EVACUATION_CANDIDATE; |
| 408 |
| 409 static const int kEvacuationCandidateOrNewSpaceMask = |
| 410 (1 << EVACUATION_CANDIDATE) | (1 << IN_FROM_SPACE) | (1 << IN_TO_SPACE); |
| 411 |
| 412 |
| 398 void SetFlag(int flag) { | 413 void SetFlag(int flag) { |
| 399 flags_ |= (1 << flag); | 414 flags_ |= (1 << flag); |
| 400 } | 415 } |
| 401 | 416 |
| 402 void ClearFlag(int flag) { | 417 void ClearFlag(int flag) { |
| 403 flags_ &= ~(1 << flag); | 418 flags_ &= ~(1 << flag); |
| 404 } | 419 } |
| 405 | 420 |
| 406 void SetFlagTo(int flag, bool value) { | 421 void SetFlagTo(int flag, bool value) { |
| 407 if (value) { | 422 if (value) { |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 602 static inline Page* Initialize(Heap* heap, | 617 static inline Page* Initialize(Heap* heap, |
| 603 MemoryChunk* chunk, | 618 MemoryChunk* chunk, |
| 604 Executability executable, | 619 Executability executable, |
| 605 PagedSpace* owner); | 620 PagedSpace* owner); |
| 606 | 621 |
| 607 void InitializeAsAnchor(PagedSpace* owner); | 622 void InitializeAsAnchor(PagedSpace* owner); |
| 608 | 623 |
| 609 bool IsEvacuationCandidate() { return IsFlagSet(EVACUATION_CANDIDATE); } | 624 bool IsEvacuationCandidate() { return IsFlagSet(EVACUATION_CANDIDATE); } |
| 610 | 625 |
| 611 bool IsEvacuationCandidateOrNewSpace() { | 626 bool IsEvacuationCandidateOrNewSpace() { |
| 612 intptr_t mask = (1 << EVACUATION_CANDIDATE) | | 627 return (flags_ & kEvacuationCandidateOrNewSpaceMask) != 0; |
| 613 (1 << IN_FROM_SPACE) | | |
| 614 (1 << IN_TO_SPACE); | |
| 615 return (flags_ & mask) != 0; | |
| 616 } | 628 } |
| 617 | 629 |
| 618 void MarkEvacuationCandidate() { SetFlag(EVACUATION_CANDIDATE); } | 630 void MarkEvacuationCandidate() { SetFlag(EVACUATION_CANDIDATE); } |
| 619 | 631 |
| 620 void ClearEvacuationCandidate() { ClearFlag(EVACUATION_CANDIDATE); } | 632 void ClearEvacuationCandidate() { ClearFlag(EVACUATION_CANDIDATE); } |
| 621 | 633 |
| 634 bool WasEvacuated() { return IsFlagSet(EVACUATED); } |
| 635 |
| 636 void MarkEvacuated() { SetFlag(EVACUATED); } |
| 637 |
| 638 void ClearEvacuated() { ClearFlag(EVACUATED); } |
| 639 |
| 622 friend class MemoryAllocator; | 640 friend class MemoryAllocator; |
| 623 }; | 641 }; |
| 624 | 642 |
| 625 | 643 |
| 626 STATIC_CHECK(sizeof(Page) <= MemoryChunk::kHeaderSize); | 644 STATIC_CHECK(sizeof(Page) <= MemoryChunk::kHeaderSize); |
| 627 | 645 |
| 628 | 646 |
| 629 class LargePage : public MemoryChunk { | 647 class LargePage : public MemoryChunk { |
| 630 public: | 648 public: |
| 631 HeapObject* GetObject() { | 649 HeapObject* GetObject() { |
| (...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1028 | 1046 |
| 1029 | 1047 |
| 1030 // ----------------------------------------------------------------------------- | 1048 // ----------------------------------------------------------------------------- |
| 1031 // A space has a circular list of pages. The next page can be accessed via | 1049 // A space has a circular list of pages. The next page can be accessed via |
| 1032 // Page::next_page() call. | 1050 // Page::next_page() call. |
| 1033 | 1051 |
| 1034 // An abstraction of allocation and relocation pointers in a page-structured | 1052 // An abstraction of allocation and relocation pointers in a page-structured |
| 1035 // space. | 1053 // space. |
| 1036 class AllocationInfo { | 1054 class AllocationInfo { |
| 1037 public: | 1055 public: |
| 1056 AllocationInfo() : top(NULL), limit(NULL) { |
| 1057 } |
| 1058 |
| 1038 Address top; // Current allocation top. | 1059 Address top; // Current allocation top. |
| 1039 Address limit; // Current allocation limit. | 1060 Address limit; // Current allocation limit. |
| 1040 | 1061 |
| 1041 #ifdef DEBUG | 1062 #ifdef DEBUG |
| 1042 bool VerifyPagedAllocation() { | 1063 bool VerifyPagedAllocation() { |
| 1043 // TODO(gc): Make this type-correct. NewSpacePage isn't a Page, | 1064 // TODO(gc): Make this type-correct. NewSpacePage isn't a Page, |
| 1044 // but NewSpace still uses AllocationInfo. | 1065 // but NewSpace still uses AllocationInfo. |
| 1045 return (Page::FromAllocationTop(top) == Page::FromAllocationTop(limit)) | 1066 return (Page::FromAllocationTop(top) == Page::FromAllocationTop(limit)) |
| 1046 && (top <= limit); | 1067 && (top <= limit); |
| 1047 } | 1068 } |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1221 bool IsVeryLong(); | 1242 bool IsVeryLong(); |
| 1222 #endif | 1243 #endif |
| 1223 | 1244 |
| 1224 void CountFreeListItems(Page* p, intptr_t* sizes); | 1245 void CountFreeListItems(Page* p, intptr_t* sizes); |
| 1225 | 1246 |
| 1226 private: | 1247 private: |
| 1227 // The size range of blocks, in bytes. | 1248 // The size range of blocks, in bytes. |
| 1228 static const int kMinBlockSize = 3 * kPointerSize; | 1249 static const int kMinBlockSize = 3 * kPointerSize; |
| 1229 static const int kMaxBlockSize = Page::kMaxHeapObjectSize; | 1250 static const int kMaxBlockSize = Page::kMaxHeapObjectSize; |
| 1230 | 1251 |
| 1252 FreeListNode* PickNodeFromList(FreeListNode** list, int* node_size); |
| 1253 |
| 1254 FreeListNode* FindNodeFor(int size_in_bytes, int* node_size); |
| 1255 |
| 1231 PagedSpace* owner_; | 1256 PagedSpace* owner_; |
| 1232 Heap* heap_; | 1257 Heap* heap_; |
| 1233 | 1258 |
| 1234 // Total available bytes in all blocks on this free list. | 1259 // Total available bytes in all blocks on this free list. |
| 1235 int available_; | 1260 int available_; |
| 1236 | 1261 |
| 1237 static const int kSmallListMin = 0x20 * kPointerSize; | 1262 static const int kSmallListMin = 0x20 * kPointerSize; |
| 1238 static const int kSmallListMax = 0xff * kPointerSize; | 1263 static const int kSmallListMax = 0xff * kPointerSize; |
| 1239 static const int kMediumListMax = 0x7ff * kPointerSize; | 1264 static const int kMediumListMax = 0x7ff * kPointerSize; |
| 1240 static const int kLargeListMax = 0x3fff * kPointerSize; | 1265 static const int kLargeListMax = 0x3fff * kPointerSize; |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1416 | 1441 |
| 1417 bool AdvanceSweeper(intptr_t bytes_to_sweep); | 1442 bool AdvanceSweeper(intptr_t bytes_to_sweep); |
| 1418 | 1443 |
| 1419 bool IsSweepingComplete() { | 1444 bool IsSweepingComplete() { |
| 1420 return !first_unswept_page_->is_valid(); | 1445 return !first_unswept_page_->is_valid(); |
| 1421 } | 1446 } |
| 1422 | 1447 |
| 1423 Page* FirstPage() { return anchor_.next_page(); } | 1448 Page* FirstPage() { return anchor_.next_page(); } |
| 1424 Page* LastPage() { return anchor_.prev_page(); } | 1449 Page* LastPage() { return anchor_.prev_page(); } |
| 1425 | 1450 |
| 1426 | |
| 1427 bool IsFragmented(Page* p) { | 1451 bool IsFragmented(Page* p) { |
| 1428 intptr_t sizes[4]; | 1452 intptr_t sizes[4]; |
| 1429 free_list_.CountFreeListItems(p, sizes); | 1453 free_list_.CountFreeListItems(p, sizes); |
| 1430 | 1454 |
| 1431 intptr_t ratio = | 1455 intptr_t ratio = |
| 1432 (sizes[0] * 5 + sizes[1]) * 100 / Page::kObjectAreaSize; | 1456 (sizes[0] * 5 + sizes[1]) * 100 / Page::kObjectAreaSize; |
| 1433 | 1457 |
| 1434 if (FLAG_trace_fragmentation) { | 1458 if (FLAG_trace_fragmentation) { |
| 1435 PrintF("%p: %d (%.2f%%) %d (%.2f%%) %d (%.2f%%) %d (%.2f%%) %s\n", | 1459 PrintF("%p: %d (%.2f%%) %d (%.2f%%) %d (%.2f%%) %d (%.2f%%) %s\n", |
| 1436 reinterpret_cast<void*>(p), | 1460 reinterpret_cast<void*>(p), |
| 1437 sizes[0], | 1461 sizes[0], |
| 1438 static_cast<double>(sizes[0] * 100) / Page::kObjectAreaSize, | 1462 static_cast<double>(sizes[0] * 100) / Page::kObjectAreaSize, |
| 1439 sizes[1], | 1463 sizes[1], |
| 1440 static_cast<double>(sizes[1] * 100) / Page::kObjectAreaSize, | 1464 static_cast<double>(sizes[1] * 100) / Page::kObjectAreaSize, |
| 1441 sizes[2], | 1465 sizes[2], |
| 1442 static_cast<double>(sizes[2] * 100) / Page::kObjectAreaSize, | 1466 static_cast<double>(sizes[2] * 100) / Page::kObjectAreaSize, |
| 1443 sizes[3], | 1467 sizes[3], |
| 1444 static_cast<double>(sizes[3] * 100) / Page::kObjectAreaSize, | 1468 static_cast<double>(sizes[3] * 100) / Page::kObjectAreaSize, |
| 1445 (ratio > 15) ? "[fragmented]" : ""); | 1469 (ratio > 15) ? "[fragmented]" : ""); |
| 1446 } | 1470 } |
| 1447 | 1471 |
| 1448 return ratio > 15; | 1472 return ratio > 15; |
| 1449 } | 1473 } |
| 1450 | 1474 |
| 1475 void EvictEvacuationCandidatesFromFreeLists(); |
| 1476 |
| 1451 protected: | 1477 protected: |
| 1452 // Maximum capacity of this space. | 1478 // Maximum capacity of this space. |
| 1453 intptr_t max_capacity_; | 1479 intptr_t max_capacity_; |
| 1454 | 1480 |
| 1455 // Accounting information for this space. | 1481 // Accounting information for this space. |
| 1456 AllocationStats accounting_stats_; | 1482 AllocationStats accounting_stats_; |
| 1457 | 1483 |
| 1458 // The dummy page that anchors the double linked list of pages. | 1484 // The dummy page that anchors the double linked list of pages. |
| 1459 Page anchor_; | 1485 Page anchor_; |
| 1460 | 1486 |
| (...skipping 712 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2173 Executability executable) | 2199 Executability executable) |
| 2174 : PagedSpace(heap, max_capacity, id, executable) { | 2200 : PagedSpace(heap, max_capacity, id, executable) { |
| 2175 page_extra_ = 0; | 2201 page_extra_ = 0; |
| 2176 } | 2202 } |
| 2177 | 2203 |
| 2178 // The limit of allocation for a page in this space. | 2204 // The limit of allocation for a page in this space. |
| 2179 virtual Address PageAllocationLimit(Page* page) { | 2205 virtual Address PageAllocationLimit(Page* page) { |
| 2180 return page->ObjectAreaEnd(); | 2206 return page->ObjectAreaEnd(); |
| 2181 } | 2207 } |
| 2182 | 2208 |
| 2183 // Prepare for full garbage collection. Resets the relocation pointer and | |
| 2184 // clears the free list. | |
| 2185 virtual void PrepareForMarkCompact(); | |
| 2186 | |
| 2187 public: | 2209 public: |
| 2188 TRACK_MEMORY("OldSpace") | 2210 TRACK_MEMORY("OldSpace") |
| 2189 }; | 2211 }; |
| 2190 | 2212 |
| 2191 | 2213 |
| 2192 // For contiguous spaces, top should be in the space (or at the end) and limit | 2214 // For contiguous spaces, top should be in the space (or at the end) and limit |
| 2193 // should be the end of the space. | 2215 // should be the end of the space. |
| 2194 #define ASSERT_SEMISPACE_ALLOCATION_INFO(info, space) \ | 2216 #define ASSERT_SEMISPACE_ALLOCATION_INFO(info, space) \ |
| 2195 ASSERT((space).page_low() <= (info).top \ | 2217 ASSERT((space).page_low() <= (info).top \ |
| 2196 && (info).top <= (space).page_high() \ | 2218 && (info).top <= (space).page_high() \ |
| (...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2518 } | 2540 } |
| 2519 // Must be small, since an iteration is used for lookup. | 2541 // Must be small, since an iteration is used for lookup. |
| 2520 static const int kMaxComments = 64; | 2542 static const int kMaxComments = 64; |
| 2521 }; | 2543 }; |
| 2522 #endif | 2544 #endif |
| 2523 | 2545 |
| 2524 | 2546 |
| 2525 } } // namespace v8::internal | 2547 } } // namespace v8::internal |
| 2526 | 2548 |
| 2527 #endif // V8_SPACES_H_ | 2549 #endif // V8_SPACES_H_ |
| OLD | NEW |