| 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 |