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 1363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1374 return reinterpret_cast<FreeListNode*>(maybe); | 1374 return reinterpret_cast<FreeListNode*>(maybe); |
1375 } | 1375 } |
1376 | 1376 |
1377 private: | 1377 private: |
1378 static const int kNextOffset = POINTER_SIZE_ALIGN(FreeSpace::kHeaderSize); | 1378 static const int kNextOffset = POINTER_SIZE_ALIGN(FreeSpace::kHeaderSize); |
1379 | 1379 |
1380 DISALLOW_IMPLICIT_CONSTRUCTORS(FreeListNode); | 1380 DISALLOW_IMPLICIT_CONSTRUCTORS(FreeListNode); |
1381 }; | 1381 }; |
1382 | 1382 |
1383 | 1383 |
1384 // The free list category holds a pointer to the top element and a pointer to | |
1385 // the end element of the linked list of free memory blocks. | |
1386 class FreeListCategory { | |
1387 public: | |
1388 FreeListCategory() : top_(NULL), end_(NULL), available_(0) {} | |
1389 | |
1390 // ConcatenateListsConcurrentAdd adds the category list to this list. | |
1391 // The add operation on the target list is non-blocking using atomic | |
1392 // operations. The resetting operation on the source list is done without | |
1393 // synchronization. ConcatenateListsConcurrentAdd is just safe to call | |
1394 // when there is just one producer thread which only adds elements to | |
1395 // the target list and one consumer thread which only removes elements | |
1396 // from the target list. The ABA problem can be ignored in the given setup. | |
1397 void ConcatenateListsConcurrentAdd(FreeListCategory* category); | |
1398 | |
1399 // ConcatenateListsConcurrentRemove adds the category list to this list. | |
1400 // The add operation on the target list is done without synchronization. | |
1401 // The resetting operation on the source list is non-blocking using atomic | |
1402 // operations. ConcatenateListsConcurrentRemove is just safe to call | |
1403 // when there is just one consumer thread which only removes elements from | |
1404 // the source list and one producer thread which only adds elements to the | |
1405 // source list. The ABA problem can be ignored in the given setup. | |
1406 void ConcatenateListsConcurrentRemove(FreeListCategory* category); | |
1407 | |
1408 void Reset(); | |
1409 | |
1410 void Free(FreeListNode* node, int size_in_bytes); | |
1411 | |
1412 FreeListNode* PickNodeFromList(int *node_size); | |
1413 | |
1414 intptr_t CountFreeListItemsInList(Page* p); | |
1415 | |
1416 intptr_t EvictFreeListItemsInList(Page* p); | |
1417 | |
1418 void RepairFreeList(Heap* heap); | |
1419 | |
1420 FreeListNode** GetTopAddress() { | |
1421 return &top_; | |
1422 } | |
1423 | |
1424 FreeListNode** GetEndAddress() { | |
1425 return &end_; | |
1426 } | |
1427 | |
1428 FreeListNode* top() const { | |
Michael Starzinger
2012/11/29 14:31:20
Let's compact the simple accessors a little by usi
Hannes Payer (out of office)
2012/11/29 15:55:02
Done.
| |
1429 return top_; | |
1430 } | |
1431 | |
1432 void set_top(FreeListNode* top) { | |
1433 top_ = top; | |
1434 } | |
1435 | |
1436 FreeListNode* end() const { | |
1437 return end_; | |
1438 } | |
1439 | |
1440 void set_end(FreeListNode* end) { | |
1441 end_ = end; | |
1442 } | |
1443 | |
1444 int available() const { | |
1445 return available_; | |
1446 } | |
1447 | |
1448 void set_available(int available) { | |
1449 available_ = available; | |
1450 } | |
1451 | |
1452 int* GetAvailableAddress() { | |
1453 return &available_; | |
1454 } | |
1455 | |
1456 #ifdef DEBUG | |
1457 intptr_t SumFreeList(); | |
1458 int FreeListLength(); | |
1459 #endif | |
1460 | |
1461 private: | |
1462 FreeListNode* top_; | |
1463 FreeListNode* end_; | |
1464 | |
1465 // Total available bytes in all blocks of this free list category. | |
1466 int available_; | |
1467 }; | |
1468 | |
1469 | |
1384 // The free list for the old space. The free list is organized in such a way | 1470 // The free list for the old space. The free list is organized in such a way |
1385 // as to encourage objects allocated around the same time to be near each | 1471 // as to encourage objects allocated around the same time to be near each |
1386 // other. The normal way to allocate is intended to be by bumping a 'top' | 1472 // other. The normal way to allocate is intended to be by bumping a 'top' |
1387 // pointer until it hits a 'limit' pointer. When the limit is hit we need to | 1473 // pointer until it hits a 'limit' pointer. When the limit is hit we need to |
1388 // find a new space to allocate from. This is done with the free list, which | 1474 // find a new space to allocate from. This is done with the free list, which |
1389 // is divided up into rough categories to cut down on waste. Having finer | 1475 // is divided up into rough categories to cut down on waste. Having finer |
1390 // categories would scatter allocation more. | 1476 // categories would scatter allocation more. |
1391 | 1477 |
1392 // The old space free list is organized in categories. | 1478 // The old space free list is organized in categories. |
1393 // 1-31 words: Such small free areas are discarded for efficiency reasons. | 1479 // 1-31 words: Such small free areas are discarded for efficiency reasons. |
(...skipping 11 matching lines...) Expand all Loading... | |
1405 // At least 16384 words. This list is for objects of 2048 words or larger. | 1491 // At least 16384 words. This list is for objects of 2048 words or larger. |
1406 // Empty pages are added to this list. These spaces are called huge. | 1492 // Empty pages are added to this list. These spaces are called huge. |
1407 class FreeList BASE_EMBEDDED { | 1493 class FreeList BASE_EMBEDDED { |
1408 public: | 1494 public: |
1409 explicit FreeList(PagedSpace* owner); | 1495 explicit FreeList(PagedSpace* owner); |
1410 | 1496 |
1411 // Clear the free list. | 1497 // Clear the free list. |
1412 void Reset(); | 1498 void Reset(); |
1413 | 1499 |
1414 // Return the number of bytes available on the free list. | 1500 // Return the number of bytes available on the free list. |
1415 intptr_t available() { return available_; } | 1501 intptr_t available() { |
1502 return small_list_.available() + medium_list_.available() + | |
1503 large_list_.available() + huge_list_.available(); | |
1504 } | |
1416 | 1505 |
1417 // Place a node on the free list. The block of size 'size_in_bytes' | 1506 // Place a node on the free list. The block of size 'size_in_bytes' |
1418 // starting at 'start' is placed on the free list. The return value is the | 1507 // starting at 'start' is placed on the free list. The return value is the |
1419 // number of bytes that have been lost due to internal fragmentation by | 1508 // number of bytes that have been lost due to internal fragmentation by |
1420 // freeing the block. Bookkeeping information will be written to the block, | 1509 // freeing the block. Bookkeeping information will be written to the block, |
1421 // i.e., its contents will be destroyed. The start address should be word | 1510 // i.e., its contents will be destroyed. The start address should be word |
1422 // aligned, and the size should be a non-zero multiple of the word size. | 1511 // aligned, and the size should be a non-zero multiple of the word size. |
1423 int Free(Address start, int size_in_bytes); | 1512 int Free(Address start, int size_in_bytes); |
1424 | 1513 |
1425 // Allocate a block of size 'size_in_bytes' from the free list. The block | 1514 // Allocate a block of size 'size_in_bytes' from the free list. The block |
1426 // is unitialized. A failure is returned if no block is available. The | 1515 // is unitialized. A failure is returned if no block is available. The |
1427 // number of bytes lost to fragmentation is returned in the output parameter | 1516 // number of bytes lost to fragmentation is returned in the output parameter |
1428 // 'wasted_bytes'. The size should be a non-zero multiple of the word size. | 1517 // 'wasted_bytes'. The size should be a non-zero multiple of the word size. |
1429 MUST_USE_RESULT HeapObject* Allocate(int size_in_bytes); | 1518 MUST_USE_RESULT HeapObject* Allocate(int size_in_bytes); |
1430 | 1519 |
1431 #ifdef DEBUG | 1520 #ifdef DEBUG |
1432 void Zap(); | 1521 void Zap(); |
1433 static intptr_t SumFreeList(FreeListNode* node); | |
1434 static int FreeListLength(FreeListNode* cur); | |
1435 intptr_t SumFreeLists(); | 1522 intptr_t SumFreeLists(); |
1436 bool IsVeryLong(); | 1523 bool IsVeryLong(); |
1437 #endif | 1524 #endif |
1438 | 1525 |
1439 // Used after booting the VM. | 1526 // Used after booting the VM. |
1440 void RepairLists(Heap* heap); | 1527 void RepairLists(Heap* heap); |
1441 | 1528 |
1442 struct SizeStats { | 1529 struct SizeStats { |
1443 intptr_t Total() { | 1530 intptr_t Total() { |
1444 return small_size_ + medium_size_ + large_size_ + huge_size_; | 1531 return small_size_ + medium_size_ + large_size_ + huge_size_; |
1445 } | 1532 } |
1446 | 1533 |
1447 intptr_t small_size_; | 1534 intptr_t small_size_; |
1448 intptr_t medium_size_; | 1535 intptr_t medium_size_; |
1449 intptr_t large_size_; | 1536 intptr_t large_size_; |
1450 intptr_t huge_size_; | 1537 intptr_t huge_size_; |
1451 }; | 1538 }; |
1452 | 1539 |
1453 void CountFreeListItems(Page* p, SizeStats* sizes); | 1540 void CountFreeListItems(Page* p, SizeStats* sizes); |
1454 | 1541 |
1455 intptr_t EvictFreeListItems(Page* p); | 1542 intptr_t EvictFreeListItems(Page* p); |
1456 | 1543 |
1457 private: | 1544 private: |
1458 // The size range of blocks, in bytes. | 1545 // The size range of blocks, in bytes. |
1459 static const int kMinBlockSize = 3 * kPointerSize; | 1546 static const int kMinBlockSize = 3 * kPointerSize; |
1460 static const int kMaxBlockSize = Page::kMaxNonCodeHeapObjectSize; | 1547 static const int kMaxBlockSize = Page::kMaxNonCodeHeapObjectSize; |
1461 | 1548 |
1462 FreeListNode* PickNodeFromList(FreeListNode** list, int* node_size); | |
1463 | |
1464 FreeListNode* FindNodeFor(int size_in_bytes, int* node_size); | 1549 FreeListNode* FindNodeFor(int size_in_bytes, int* node_size); |
1465 | 1550 |
1466 PagedSpace* owner_; | 1551 PagedSpace* owner_; |
1467 Heap* heap_; | 1552 Heap* heap_; |
1468 | 1553 |
1469 // Total available bytes in all blocks on this free list. | |
1470 int available_; | |
1471 | |
1472 static const int kSmallListMin = 0x20 * kPointerSize; | 1554 static const int kSmallListMin = 0x20 * kPointerSize; |
1473 static const int kSmallListMax = 0xff * kPointerSize; | 1555 static const int kSmallListMax = 0xff * kPointerSize; |
1474 static const int kMediumListMax = 0x7ff * kPointerSize; | 1556 static const int kMediumListMax = 0x7ff * kPointerSize; |
1475 static const int kLargeListMax = 0x3fff * kPointerSize; | 1557 static const int kLargeListMax = 0x3fff * kPointerSize; |
1476 static const int kSmallAllocationMax = kSmallListMin - kPointerSize; | 1558 static const int kSmallAllocationMax = kSmallListMin - kPointerSize; |
1477 static const int kMediumAllocationMax = kSmallListMax; | 1559 static const int kMediumAllocationMax = kSmallListMax; |
1478 static const int kLargeAllocationMax = kMediumListMax; | 1560 static const int kLargeAllocationMax = kMediumListMax; |
1479 FreeListNode* small_list_; | 1561 FreeListCategory small_list_; |
1480 FreeListNode* medium_list_; | 1562 FreeListCategory medium_list_; |
1481 FreeListNode* large_list_; | 1563 FreeListCategory large_list_; |
1482 FreeListNode* huge_list_; | 1564 FreeListCategory huge_list_; |
1483 | 1565 |
1484 DISALLOW_IMPLICIT_CONSTRUCTORS(FreeList); | 1566 DISALLOW_IMPLICIT_CONSTRUCTORS(FreeList); |
1485 }; | 1567 }; |
1486 | 1568 |
1487 | 1569 |
1488 class PagedSpace : public Space { | 1570 class PagedSpace : public Space { |
1489 public: | 1571 public: |
1490 // Creates a space with a maximum capacity, and an id. | 1572 // Creates a space with a maximum capacity, and an id. |
1491 PagedSpace(Heap* heap, | 1573 PagedSpace(Heap* heap, |
1492 intptr_t max_capacity, | 1574 intptr_t max_capacity, |
(...skipping 1235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2728 } | 2810 } |
2729 // Must be small, since an iteration is used for lookup. | 2811 // Must be small, since an iteration is used for lookup. |
2730 static const int kMaxComments = 64; | 2812 static const int kMaxComments = 64; |
2731 }; | 2813 }; |
2732 #endif | 2814 #endif |
2733 | 2815 |
2734 | 2816 |
2735 } } // namespace v8::internal | 2817 } } // namespace v8::internal |
2736 | 2818 |
2737 #endif // V8_SPACES_H_ | 2819 #endif // V8_SPACES_H_ |
OLD | NEW |