OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
8 #include "src/base/platform/platform.h" | 8 #include "src/base/platform/platform.h" |
9 #include "src/full-codegen.h" | 9 #include "src/full-codegen.h" |
10 #include "src/heap/mark-compact.h" | 10 #include "src/heap/mark-compact.h" |
(...skipping 1241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1252 chunk_base_ = NULL; | 1252 chunk_base_ = NULL; |
1253 chunk_size_ = 0; | 1253 chunk_size_ = 0; |
1254 } | 1254 } |
1255 | 1255 |
1256 | 1256 |
1257 void NewSpace::Flip() { SemiSpace::Swap(&from_space_, &to_space_); } | 1257 void NewSpace::Flip() { SemiSpace::Swap(&from_space_, &to_space_); } |
1258 | 1258 |
1259 | 1259 |
1260 void NewSpace::Grow() { | 1260 void NewSpace::Grow() { |
1261 // Double the semispace size but only up to maximum capacity. | 1261 // Double the semispace size but only up to maximum capacity. |
1262 DCHECK(Capacity() < MaximumCapacity()); | 1262 DCHECK(TotalCapacity() < MaximumCapacity()); |
1263 int new_capacity = Min(MaximumCapacity(), 2 * static_cast<int>(Capacity())); | 1263 int new_capacity = |
| 1264 Min(MaximumCapacity(), 2 * static_cast<int>(TotalCapacity())); |
1264 if (to_space_.GrowTo(new_capacity)) { | 1265 if (to_space_.GrowTo(new_capacity)) { |
1265 // Only grow from space if we managed to grow to-space. | 1266 // Only grow from space if we managed to grow to-space. |
1266 if (!from_space_.GrowTo(new_capacity)) { | 1267 if (!from_space_.GrowTo(new_capacity)) { |
1267 // If we managed to grow to-space but couldn't grow from-space, | 1268 // If we managed to grow to-space but couldn't grow from-space, |
1268 // attempt to shrink to-space. | 1269 // attempt to shrink to-space. |
1269 if (!to_space_.ShrinkTo(from_space_.Capacity())) { | 1270 if (!to_space_.ShrinkTo(from_space_.TotalCapacity())) { |
1270 // We are in an inconsistent state because we could not | 1271 // We are in an inconsistent state because we could not |
1271 // commit/uncommit memory from new space. | 1272 // commit/uncommit memory from new space. |
1272 V8::FatalProcessOutOfMemory("Failed to grow new space."); | 1273 V8::FatalProcessOutOfMemory("Failed to grow new space."); |
1273 } | 1274 } |
1274 } | 1275 } |
1275 } | 1276 } |
1276 DCHECK_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); | 1277 DCHECK_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); |
1277 } | 1278 } |
1278 | 1279 |
1279 | 1280 |
1280 void NewSpace::Shrink() { | 1281 void NewSpace::Shrink() { |
1281 int new_capacity = Max(InitialCapacity(), 2 * SizeAsInt()); | 1282 int new_capacity = Max(InitialTotalCapacity(), 2 * SizeAsInt()); |
1282 int rounded_new_capacity = RoundUp(new_capacity, Page::kPageSize); | 1283 int rounded_new_capacity = RoundUp(new_capacity, Page::kPageSize); |
1283 if (rounded_new_capacity < Capacity() && | 1284 if (rounded_new_capacity < TotalCapacity() && |
1284 to_space_.ShrinkTo(rounded_new_capacity)) { | 1285 to_space_.ShrinkTo(rounded_new_capacity)) { |
1285 // Only shrink from-space if we managed to shrink to-space. | 1286 // Only shrink from-space if we managed to shrink to-space. |
1286 from_space_.Reset(); | 1287 from_space_.Reset(); |
1287 if (!from_space_.ShrinkTo(rounded_new_capacity)) { | 1288 if (!from_space_.ShrinkTo(rounded_new_capacity)) { |
1288 // If we managed to shrink to-space but couldn't shrink from | 1289 // If we managed to shrink to-space but couldn't shrink from |
1289 // space, attempt to grow to-space again. | 1290 // space, attempt to grow to-space again. |
1290 if (!to_space_.GrowTo(from_space_.Capacity())) { | 1291 if (!to_space_.GrowTo(from_space_.TotalCapacity())) { |
1291 // We are in an inconsistent state because we could not | 1292 // We are in an inconsistent state because we could not |
1292 // commit/uncommit memory from new space. | 1293 // commit/uncommit memory from new space. |
1293 V8::FatalProcessOutOfMemory("Failed to shrink new space."); | 1294 V8::FatalProcessOutOfMemory("Failed to shrink new space."); |
1294 } | 1295 } |
1295 } | 1296 } |
1296 } | 1297 } |
1297 DCHECK_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); | 1298 DCHECK_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); |
1298 } | 1299 } |
1299 | 1300 |
1300 | 1301 |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1458 | 1459 |
1459 void SemiSpace::SetUp(Address start, int initial_capacity, | 1460 void SemiSpace::SetUp(Address start, int initial_capacity, |
1460 int maximum_capacity) { | 1461 int maximum_capacity) { |
1461 // Creates a space in the young generation. The constructor does not | 1462 // Creates a space in the young generation. The constructor does not |
1462 // allocate memory from the OS. A SemiSpace is given a contiguous chunk of | 1463 // allocate memory from the OS. A SemiSpace is given a contiguous chunk of |
1463 // memory of size 'capacity' when set up, and does not grow or shrink | 1464 // memory of size 'capacity' when set up, and does not grow or shrink |
1464 // otherwise. In the mark-compact collector, the memory region of the from | 1465 // otherwise. In the mark-compact collector, the memory region of the from |
1465 // space is used as the marking stack. It requires contiguous memory | 1466 // space is used as the marking stack. It requires contiguous memory |
1466 // addresses. | 1467 // addresses. |
1467 DCHECK(maximum_capacity >= Page::kPageSize); | 1468 DCHECK(maximum_capacity >= Page::kPageSize); |
1468 initial_capacity_ = RoundDown(initial_capacity, Page::kPageSize); | 1469 initial_total_capacity_ = RoundDown(initial_capacity, Page::kPageSize); |
1469 capacity_ = initial_capacity; | 1470 total_capacity_ = initial_capacity; |
1470 maximum_capacity_ = RoundDown(maximum_capacity, Page::kPageSize); | 1471 maximum_total_capacity_ = RoundDown(maximum_capacity, Page::kPageSize); |
1471 maximum_committed_ = 0; | 1472 maximum_committed_ = 0; |
1472 committed_ = false; | 1473 committed_ = false; |
1473 start_ = start; | 1474 start_ = start; |
1474 address_mask_ = ~(maximum_capacity - 1); | 1475 address_mask_ = ~(maximum_capacity - 1); |
1475 object_mask_ = address_mask_ | kHeapObjectTagMask; | 1476 object_mask_ = address_mask_ | kHeapObjectTagMask; |
1476 object_expected_ = reinterpret_cast<uintptr_t>(start) | kHeapObjectTag; | 1477 object_expected_ = reinterpret_cast<uintptr_t>(start) | kHeapObjectTag; |
1477 age_mark_ = start_; | 1478 age_mark_ = start_; |
1478 } | 1479 } |
1479 | 1480 |
1480 | 1481 |
1481 void SemiSpace::TearDown() { | 1482 void SemiSpace::TearDown() { |
1482 start_ = NULL; | 1483 start_ = NULL; |
1483 capacity_ = 0; | 1484 total_capacity_ = 0; |
1484 } | 1485 } |
1485 | 1486 |
1486 | 1487 |
1487 bool SemiSpace::Commit() { | 1488 bool SemiSpace::Commit() { |
1488 DCHECK(!is_committed()); | 1489 DCHECK(!is_committed()); |
1489 int pages = capacity_ / Page::kPageSize; | 1490 int pages = total_capacity_ / Page::kPageSize; |
1490 if (!heap()->isolate()->memory_allocator()->CommitBlock(start_, capacity_, | 1491 if (!heap()->isolate()->memory_allocator()->CommitBlock( |
1491 executable())) { | 1492 start_, total_capacity_, executable())) { |
1492 return false; | 1493 return false; |
1493 } | 1494 } |
1494 | 1495 |
1495 NewSpacePage* current = anchor(); | 1496 NewSpacePage* current = anchor(); |
1496 for (int i = 0; i < pages; i++) { | 1497 for (int i = 0; i < pages; i++) { |
1497 NewSpacePage* new_page = | 1498 NewSpacePage* new_page = |
1498 NewSpacePage::Initialize(heap(), start_ + i * Page::kPageSize, this); | 1499 NewSpacePage::Initialize(heap(), start_ + i * Page::kPageSize, this); |
1499 new_page->InsertAfter(current); | 1500 new_page->InsertAfter(current); |
1500 current = new_page; | 1501 current = new_page; |
1501 } | 1502 } |
1502 | 1503 |
1503 SetCapacity(capacity_); | 1504 SetCapacity(total_capacity_); |
1504 committed_ = true; | 1505 committed_ = true; |
1505 Reset(); | 1506 Reset(); |
1506 return true; | 1507 return true; |
1507 } | 1508 } |
1508 | 1509 |
1509 | 1510 |
1510 bool SemiSpace::Uncommit() { | 1511 bool SemiSpace::Uncommit() { |
1511 DCHECK(is_committed()); | 1512 DCHECK(is_committed()); |
1512 Address start = start_ + maximum_capacity_ - capacity_; | 1513 Address start = start_ + maximum_total_capacity_ - total_capacity_; |
1513 if (!heap()->isolate()->memory_allocator()->UncommitBlock(start, capacity_)) { | 1514 if (!heap()->isolate()->memory_allocator()->UncommitBlock(start, |
| 1515 total_capacity_)) { |
1514 return false; | 1516 return false; |
1515 } | 1517 } |
1516 anchor()->set_next_page(anchor()); | 1518 anchor()->set_next_page(anchor()); |
1517 anchor()->set_prev_page(anchor()); | 1519 anchor()->set_prev_page(anchor()); |
1518 | 1520 |
1519 committed_ = false; | 1521 committed_ = false; |
1520 return true; | 1522 return true; |
1521 } | 1523 } |
1522 | 1524 |
1523 | 1525 |
1524 size_t SemiSpace::CommittedPhysicalMemory() { | 1526 size_t SemiSpace::CommittedPhysicalMemory() { |
1525 if (!is_committed()) return 0; | 1527 if (!is_committed()) return 0; |
1526 size_t size = 0; | 1528 size_t size = 0; |
1527 NewSpacePageIterator it(this); | 1529 NewSpacePageIterator it(this); |
1528 while (it.has_next()) { | 1530 while (it.has_next()) { |
1529 size += it.next()->CommittedPhysicalMemory(); | 1531 size += it.next()->CommittedPhysicalMemory(); |
1530 } | 1532 } |
1531 return size; | 1533 return size; |
1532 } | 1534 } |
1533 | 1535 |
1534 | 1536 |
1535 bool SemiSpace::GrowTo(int new_capacity) { | 1537 bool SemiSpace::GrowTo(int new_capacity) { |
1536 if (!is_committed()) { | 1538 if (!is_committed()) { |
1537 if (!Commit()) return false; | 1539 if (!Commit()) return false; |
1538 } | 1540 } |
1539 DCHECK((new_capacity & Page::kPageAlignmentMask) == 0); | 1541 DCHECK((new_capacity & Page::kPageAlignmentMask) == 0); |
1540 DCHECK(new_capacity <= maximum_capacity_); | 1542 DCHECK(new_capacity <= maximum_total_capacity_); |
1541 DCHECK(new_capacity > capacity_); | 1543 DCHECK(new_capacity > total_capacity_); |
1542 int pages_before = capacity_ / Page::kPageSize; | 1544 int pages_before = total_capacity_ / Page::kPageSize; |
1543 int pages_after = new_capacity / Page::kPageSize; | 1545 int pages_after = new_capacity / Page::kPageSize; |
1544 | 1546 |
1545 size_t delta = new_capacity - capacity_; | 1547 size_t delta = new_capacity - total_capacity_; |
1546 | 1548 |
1547 DCHECK(IsAligned(delta, base::OS::AllocateAlignment())); | 1549 DCHECK(IsAligned(delta, base::OS::AllocateAlignment())); |
1548 if (!heap()->isolate()->memory_allocator()->CommitBlock( | 1550 if (!heap()->isolate()->memory_allocator()->CommitBlock( |
1549 start_ + capacity_, delta, executable())) { | 1551 start_ + total_capacity_, delta, executable())) { |
1550 return false; | 1552 return false; |
1551 } | 1553 } |
1552 SetCapacity(new_capacity); | 1554 SetCapacity(new_capacity); |
1553 NewSpacePage* last_page = anchor()->prev_page(); | 1555 NewSpacePage* last_page = anchor()->prev_page(); |
1554 DCHECK(last_page != anchor()); | 1556 DCHECK(last_page != anchor()); |
1555 for (int i = pages_before; i < pages_after; i++) { | 1557 for (int i = pages_before; i < pages_after; i++) { |
1556 Address page_address = start_ + i * Page::kPageSize; | 1558 Address page_address = start_ + i * Page::kPageSize; |
1557 NewSpacePage* new_page = | 1559 NewSpacePage* new_page = |
1558 NewSpacePage::Initialize(heap(), page_address, this); | 1560 NewSpacePage::Initialize(heap(), page_address, this); |
1559 new_page->InsertAfter(last_page); | 1561 new_page->InsertAfter(last_page); |
1560 Bitmap::Clear(new_page); | 1562 Bitmap::Clear(new_page); |
1561 // Duplicate the flags that was set on the old page. | 1563 // Duplicate the flags that was set on the old page. |
1562 new_page->SetFlags(last_page->GetFlags(), | 1564 new_page->SetFlags(last_page->GetFlags(), |
1563 NewSpacePage::kCopyOnFlipFlagsMask); | 1565 NewSpacePage::kCopyOnFlipFlagsMask); |
1564 last_page = new_page; | 1566 last_page = new_page; |
1565 } | 1567 } |
1566 return true; | 1568 return true; |
1567 } | 1569 } |
1568 | 1570 |
1569 | 1571 |
1570 bool SemiSpace::ShrinkTo(int new_capacity) { | 1572 bool SemiSpace::ShrinkTo(int new_capacity) { |
1571 DCHECK((new_capacity & Page::kPageAlignmentMask) == 0); | 1573 DCHECK((new_capacity & Page::kPageAlignmentMask) == 0); |
1572 DCHECK(new_capacity >= initial_capacity_); | 1574 DCHECK(new_capacity >= initial_total_capacity_); |
1573 DCHECK(new_capacity < capacity_); | 1575 DCHECK(new_capacity < total_capacity_); |
1574 if (is_committed()) { | 1576 if (is_committed()) { |
1575 size_t delta = capacity_ - new_capacity; | 1577 size_t delta = total_capacity_ - new_capacity; |
1576 DCHECK(IsAligned(delta, base::OS::AllocateAlignment())); | 1578 DCHECK(IsAligned(delta, base::OS::AllocateAlignment())); |
1577 | 1579 |
1578 MemoryAllocator* allocator = heap()->isolate()->memory_allocator(); | 1580 MemoryAllocator* allocator = heap()->isolate()->memory_allocator(); |
1579 if (!allocator->UncommitBlock(start_ + new_capacity, delta)) { | 1581 if (!allocator->UncommitBlock(start_ + new_capacity, delta)) { |
1580 return false; | 1582 return false; |
1581 } | 1583 } |
1582 | 1584 |
1583 int pages_after = new_capacity / Page::kPageSize; | 1585 int pages_after = new_capacity / Page::kPageSize; |
1584 NewSpacePage* new_last_page = | 1586 NewSpacePage* new_last_page = |
1585 NewSpacePage::FromAddress(start_ + (pages_after - 1) * Page::kPageSize); | 1587 NewSpacePage::FromAddress(start_ + (pages_after - 1) * Page::kPageSize); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1645 // Swap to/from-space bits on pages. | 1647 // Swap to/from-space bits on pages. |
1646 // Copy GC flags from old active space (from-space) to new (to-space). | 1648 // Copy GC flags from old active space (from-space) to new (to-space). |
1647 intptr_t flags = from->current_page()->GetFlags(); | 1649 intptr_t flags = from->current_page()->GetFlags(); |
1648 to->FlipPages(flags, NewSpacePage::kCopyOnFlipFlagsMask); | 1650 to->FlipPages(flags, NewSpacePage::kCopyOnFlipFlagsMask); |
1649 | 1651 |
1650 from->FlipPages(0, 0); | 1652 from->FlipPages(0, 0); |
1651 } | 1653 } |
1652 | 1654 |
1653 | 1655 |
1654 void SemiSpace::SetCapacity(int new_capacity) { | 1656 void SemiSpace::SetCapacity(int new_capacity) { |
1655 capacity_ = new_capacity; | 1657 total_capacity_ = new_capacity; |
1656 if (capacity_ > maximum_committed_) { | 1658 if (total_capacity_ > maximum_committed_) { |
1657 maximum_committed_ = capacity_; | 1659 maximum_committed_ = total_capacity_; |
1658 } | 1660 } |
1659 } | 1661 } |
1660 | 1662 |
1661 | 1663 |
1662 void SemiSpace::set_age_mark(Address mark) { | 1664 void SemiSpace::set_age_mark(Address mark) { |
1663 DCHECK(NewSpacePage::FromLimit(mark)->semi_space() == this); | 1665 DCHECK(NewSpacePage::FromLimit(mark)->semi_space() == this); |
1664 age_mark_ = mark; | 1666 age_mark_ = mark; |
1665 // Mark all pages up to the one containing mark. | 1667 // Mark all pages up to the one containing mark. |
1666 NewSpacePageIterator it(space_start(), mark); | 1668 NewSpacePageIterator it(space_start(), mark); |
1667 while (it.has_next()) { | 1669 while (it.has_next()) { |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1888 info[i].bytes())); | 1890 info[i].bytes())); |
1889 } | 1891 } |
1890 } | 1892 } |
1891 LOG(isolate, HeapSampleEndEvent("NewSpace", description)); | 1893 LOG(isolate, HeapSampleEndEvent("NewSpace", description)); |
1892 } | 1894 } |
1893 | 1895 |
1894 | 1896 |
1895 void NewSpace::ReportStatistics() { | 1897 void NewSpace::ReportStatistics() { |
1896 #ifdef DEBUG | 1898 #ifdef DEBUG |
1897 if (FLAG_heap_stats) { | 1899 if (FLAG_heap_stats) { |
1898 float pct = static_cast<float>(Available()) / Capacity(); | 1900 float pct = static_cast<float>(Available()) / TotalCapacity(); |
1899 PrintF(" capacity: %" V8_PTR_PREFIX | 1901 PrintF(" capacity: %" V8_PTR_PREFIX |
1900 "d" | 1902 "d" |
1901 ", available: %" V8_PTR_PREFIX "d, %%%d\n", | 1903 ", available: %" V8_PTR_PREFIX "d, %%%d\n", |
1902 Capacity(), Available(), static_cast<int>(pct * 100)); | 1904 TotalCapacity(), Available(), static_cast<int>(pct * 100)); |
1903 PrintF("\n Object Histogram:\n"); | 1905 PrintF("\n Object Histogram:\n"); |
1904 for (int i = 0; i <= LAST_TYPE; i++) { | 1906 for (int i = 0; i <= LAST_TYPE; i++) { |
1905 if (allocated_histogram_[i].number() > 0) { | 1907 if (allocated_histogram_[i].number() > 0) { |
1906 PrintF(" %-34s%10d (%10d bytes)\n", allocated_histogram_[i].name(), | 1908 PrintF(" %-34s%10d (%10d bytes)\n", allocated_histogram_[i].name(), |
1907 allocated_histogram_[i].number(), | 1909 allocated_histogram_[i].number(), |
1908 allocated_histogram_[i].bytes()); | 1910 allocated_histogram_[i].bytes()); |
1909 } | 1911 } |
1910 } | 1912 } |
1911 PrintF("\n"); | 1913 PrintF("\n"); |
1912 } | 1914 } |
(...skipping 1183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3096 object->ShortPrint(); | 3098 object->ShortPrint(); |
3097 PrintF("\n"); | 3099 PrintF("\n"); |
3098 } | 3100 } |
3099 printf(" --------------------------------------\n"); | 3101 printf(" --------------------------------------\n"); |
3100 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); | 3102 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); |
3101 } | 3103 } |
3102 | 3104 |
3103 #endif // DEBUG | 3105 #endif // DEBUG |
3104 } | 3106 } |
3105 } // namespace v8::internal | 3107 } // namespace v8::internal |
OLD | NEW |