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 |