Chromium Code Reviews| 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 |