| 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 1177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1188 | 1188 |
| 1189 | 1189 |
| 1190 bool NewSpace::SetUp(int reserved_semispace_capacity, | 1190 bool NewSpace::SetUp(int reserved_semispace_capacity, |
| 1191 int maximum_semispace_capacity) { | 1191 int maximum_semispace_capacity) { |
| 1192 // Set up new space based on the preallocated memory block defined by | 1192 // Set up new space based on the preallocated memory block defined by |
| 1193 // start and size. The provided space is divided into two semi-spaces. | 1193 // start and size. The provided space is divided into two semi-spaces. |
| 1194 // To support fast containment testing in the new space, the size of | 1194 // To support fast containment testing in the new space, the size of |
| 1195 // this chunk must be a power of two and it must be aligned to its size. | 1195 // this chunk must be a power of two and it must be aligned to its size. |
| 1196 int initial_semispace_capacity = heap()->InitialSemiSpaceSize(); | 1196 int initial_semispace_capacity = heap()->InitialSemiSpaceSize(); |
| 1197 | 1197 |
| 1198 int target_semispace_capacity = heap()->TargetSemiSpaceSize(); |
| 1199 |
| 1198 size_t size = 2 * reserved_semispace_capacity; | 1200 size_t size = 2 * reserved_semispace_capacity; |
| 1199 Address base = heap()->isolate()->memory_allocator()->ReserveAlignedMemory( | 1201 Address base = heap()->isolate()->memory_allocator()->ReserveAlignedMemory( |
| 1200 size, size, &reservation_); | 1202 size, size, &reservation_); |
| 1201 if (base == NULL) return false; | 1203 if (base == NULL) return false; |
| 1202 | 1204 |
| 1203 chunk_base_ = base; | 1205 chunk_base_ = base; |
| 1204 chunk_size_ = static_cast<uintptr_t>(size); | 1206 chunk_size_ = static_cast<uintptr_t>(size); |
| 1205 LOG(heap()->isolate(), NewEvent("InitialChunk", chunk_base_, chunk_size_)); | 1207 LOG(heap()->isolate(), NewEvent("InitialChunk", chunk_base_, chunk_size_)); |
| 1206 | 1208 |
| 1207 DCHECK(initial_semispace_capacity <= maximum_semispace_capacity); | 1209 DCHECK(initial_semispace_capacity <= maximum_semispace_capacity); |
| 1208 DCHECK(base::bits::IsPowerOfTwo32(maximum_semispace_capacity)); | 1210 DCHECK(base::bits::IsPowerOfTwo32(maximum_semispace_capacity)); |
| 1209 | 1211 |
| 1210 // Allocate and set up the histogram arrays if necessary. | 1212 // Allocate and set up the histogram arrays if necessary. |
| 1211 allocated_histogram_ = NewArray<HistogramInfo>(LAST_TYPE + 1); | 1213 allocated_histogram_ = NewArray<HistogramInfo>(LAST_TYPE + 1); |
| 1212 promoted_histogram_ = NewArray<HistogramInfo>(LAST_TYPE + 1); | 1214 promoted_histogram_ = NewArray<HistogramInfo>(LAST_TYPE + 1); |
| 1213 | 1215 |
| 1214 #define SET_NAME(name) \ | 1216 #define SET_NAME(name) \ |
| 1215 allocated_histogram_[name].set_name(#name); \ | 1217 allocated_histogram_[name].set_name(#name); \ |
| 1216 promoted_histogram_[name].set_name(#name); | 1218 promoted_histogram_[name].set_name(#name); |
| 1217 INSTANCE_TYPE_LIST(SET_NAME) | 1219 INSTANCE_TYPE_LIST(SET_NAME) |
| 1218 #undef SET_NAME | 1220 #undef SET_NAME |
| 1219 | 1221 |
| 1220 DCHECK(reserved_semispace_capacity == heap()->ReservedSemiSpaceSize()); | 1222 DCHECK(reserved_semispace_capacity == heap()->ReservedSemiSpaceSize()); |
| 1221 DCHECK(static_cast<intptr_t>(chunk_size_) >= | 1223 DCHECK(static_cast<intptr_t>(chunk_size_) >= |
| 1222 2 * heap()->ReservedSemiSpaceSize()); | 1224 2 * heap()->ReservedSemiSpaceSize()); |
| 1223 DCHECK(IsAddressAligned(chunk_base_, 2 * reserved_semispace_capacity, 0)); | 1225 DCHECK(IsAddressAligned(chunk_base_, 2 * reserved_semispace_capacity, 0)); |
| 1224 | 1226 |
| 1225 to_space_.SetUp(chunk_base_, initial_semispace_capacity, | 1227 to_space_.SetUp(chunk_base_, initial_semispace_capacity, |
| 1226 maximum_semispace_capacity); | 1228 target_semispace_capacity, maximum_semispace_capacity); |
| 1227 from_space_.SetUp(chunk_base_ + reserved_semispace_capacity, | 1229 from_space_.SetUp(chunk_base_ + reserved_semispace_capacity, |
| 1228 initial_semispace_capacity, maximum_semispace_capacity); | 1230 initial_semispace_capacity, target_semispace_capacity, |
| 1231 maximum_semispace_capacity); |
| 1229 if (!to_space_.Commit()) { | 1232 if (!to_space_.Commit()) { |
| 1230 return false; | 1233 return false; |
| 1231 } | 1234 } |
| 1232 DCHECK(!from_space_.is_committed()); // No need to use memory yet. | 1235 DCHECK(!from_space_.is_committed()); // No need to use memory yet. |
| 1233 | 1236 |
| 1234 start_ = chunk_base_; | 1237 start_ = chunk_base_; |
| 1235 address_mask_ = ~(2 * reserved_semispace_capacity - 1); | 1238 address_mask_ = ~(2 * reserved_semispace_capacity - 1); |
| 1236 object_mask_ = address_mask_ | kHeapObjectTagMask; | 1239 object_mask_ = address_mask_ | kHeapObjectTagMask; |
| 1237 object_expected_ = reinterpret_cast<uintptr_t>(start_) | kHeapObjectTag; | 1240 object_expected_ = reinterpret_cast<uintptr_t>(start_) | kHeapObjectTag; |
| 1238 | 1241 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1278 int new_capacity = | 1281 int new_capacity = |
| 1279 Min(MaximumCapacity(), 2 * static_cast<int>(TotalCapacity())); | 1282 Min(MaximumCapacity(), 2 * static_cast<int>(TotalCapacity())); |
| 1280 if (to_space_.GrowTo(new_capacity)) { | 1283 if (to_space_.GrowTo(new_capacity)) { |
| 1281 // Only grow from space if we managed to grow to-space. | 1284 // Only grow from space if we managed to grow to-space. |
| 1282 if (!from_space_.GrowTo(new_capacity)) { | 1285 if (!from_space_.GrowTo(new_capacity)) { |
| 1283 // If we managed to grow to-space but couldn't grow from-space, | 1286 // If we managed to grow to-space but couldn't grow from-space, |
| 1284 // attempt to shrink to-space. | 1287 // attempt to shrink to-space. |
| 1285 if (!to_space_.ShrinkTo(from_space_.TotalCapacity())) { | 1288 if (!to_space_.ShrinkTo(from_space_.TotalCapacity())) { |
| 1286 // We are in an inconsistent state because we could not | 1289 // We are in an inconsistent state because we could not |
| 1287 // commit/uncommit memory from new space. | 1290 // commit/uncommit memory from new space. |
| 1288 V8::FatalProcessOutOfMemory("Failed to grow new space."); | 1291 CHECK(false); |
| 1289 } | 1292 } |
| 1290 } | 1293 } |
| 1291 } | 1294 } |
| 1292 DCHECK_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); | 1295 DCHECK_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); |
| 1293 } | 1296 } |
| 1294 | 1297 |
| 1295 | 1298 |
| 1299 bool NewSpace::GrowOnePage() { |
| 1300 if (TotalCapacity() == MaximumCapacity()) return false; |
| 1301 int new_capacity = static_cast<int>(TotalCapacity()) + Page::kPageSize; |
| 1302 if (to_space_.GrowTo(new_capacity)) { |
| 1303 // Only grow from space if we managed to grow to-space and the from space |
| 1304 // is actually committed. |
| 1305 if (from_space_.is_committed()) { |
| 1306 if (!from_space_.GrowTo(new_capacity)) { |
| 1307 // If we managed to grow to-space but couldn't grow from-space, |
| 1308 // attempt to shrink to-space. |
| 1309 if (!to_space_.ShrinkTo(from_space_.TotalCapacity())) { |
| 1310 // We are in an inconsistent state because we could not |
| 1311 // commit/uncommit memory from new space. |
| 1312 CHECK(false); |
| 1313 } |
| 1314 return false; |
| 1315 } |
| 1316 } else { |
| 1317 if (!from_space_.SetTotalCapacity(new_capacity)) { |
| 1318 // Can't really happen, but better safe than sorry. |
| 1319 CHECK(false); |
| 1320 } |
| 1321 } |
| 1322 DCHECK_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); |
| 1323 return true; |
| 1324 } |
| 1325 return false; |
| 1326 } |
| 1327 |
| 1328 |
| 1296 void NewSpace::Shrink() { | 1329 void NewSpace::Shrink() { |
| 1297 int new_capacity = Max(InitialTotalCapacity(), 2 * SizeAsInt()); | 1330 int new_capacity = Max(InitialTotalCapacity(), 2 * SizeAsInt()); |
| 1298 int rounded_new_capacity = RoundUp(new_capacity, Page::kPageSize); | 1331 int rounded_new_capacity = RoundUp(new_capacity, Page::kPageSize); |
| 1299 if (rounded_new_capacity < TotalCapacity() && | 1332 if (rounded_new_capacity < TotalCapacity() && |
| 1300 to_space_.ShrinkTo(rounded_new_capacity)) { | 1333 to_space_.ShrinkTo(rounded_new_capacity)) { |
| 1301 // Only shrink from-space if we managed to shrink to-space. | 1334 // Only shrink from-space if we managed to shrink to-space. |
| 1302 from_space_.Reset(); | 1335 from_space_.Reset(); |
| 1303 if (!from_space_.ShrinkTo(rounded_new_capacity)) { | 1336 if (!from_space_.ShrinkTo(rounded_new_capacity)) { |
| 1304 // If we managed to shrink to-space but couldn't shrink from | 1337 // If we managed to shrink to-space but couldn't shrink from |
| 1305 // space, attempt to grow to-space again. | 1338 // space, attempt to grow to-space again. |
| 1306 if (!to_space_.GrowTo(from_space_.TotalCapacity())) { | 1339 if (!to_space_.GrowTo(from_space_.TotalCapacity())) { |
| 1307 // We are in an inconsistent state because we could not | 1340 // We are in an inconsistent state because we could not |
| 1308 // commit/uncommit memory from new space. | 1341 // commit/uncommit memory from new space. |
| 1309 V8::FatalProcessOutOfMemory("Failed to shrink new space."); | 1342 CHECK(false); |
| 1310 } | 1343 } |
| 1311 } | 1344 } |
| 1312 } | 1345 } |
| 1313 DCHECK_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); | 1346 DCHECK_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); |
| 1314 } | 1347 } |
| 1315 | 1348 |
| 1316 | 1349 |
| 1317 void NewSpace::UpdateAllocationInfo() { | 1350 void NewSpace::UpdateAllocationInfo() { |
| 1318 MemoryChunk::UpdateHighWaterMark(allocation_info_.top()); | 1351 MemoryChunk::UpdateHighWaterMark(allocation_info_.top()); |
| 1319 allocation_info_.set_top(to_space_.page_low()); | 1352 allocation_info_.set_top(to_space_.page_low()); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1360 if (NewSpacePage::IsAtStart(top)) { | 1393 if (NewSpacePage::IsAtStart(top)) { |
| 1361 // The current page is already empty. Don't try to make another. | 1394 // The current page is already empty. Don't try to make another. |
| 1362 | 1395 |
| 1363 // We should only get here if someone asks to allocate more | 1396 // We should only get here if someone asks to allocate more |
| 1364 // than what can be stored in a single page. | 1397 // than what can be stored in a single page. |
| 1365 // TODO(gc): Change the limit on new-space allocation to prevent this | 1398 // TODO(gc): Change the limit on new-space allocation to prevent this |
| 1366 // from happening (all such allocations should go directly to LOSpace). | 1399 // from happening (all such allocations should go directly to LOSpace). |
| 1367 return false; | 1400 return false; |
| 1368 } | 1401 } |
| 1369 if (!to_space_.AdvancePage()) { | 1402 if (!to_space_.AdvancePage()) { |
| 1370 // Failed to get a new page in to-space. | 1403 // Check if we reached the target capacity yet. If not, try to commit a page |
| 1371 return false; | 1404 // and continue. |
| 1405 if ((to_space_.TotalCapacity() < to_space_.TargetCapacity()) && |
| 1406 GrowOnePage()) { |
| 1407 if (!to_space_.AdvancePage()) { |
| 1408 // It doesn't make sense that we managed to commit a page, but can't use |
| 1409 // it. |
| 1410 CHECK(false); |
| 1411 } |
| 1412 } else { |
| 1413 // Failed to get a new page in to-space. |
| 1414 return false; |
| 1415 } |
| 1372 } | 1416 } |
| 1373 | 1417 |
| 1374 // Clear remainder of current page. | 1418 // Clear remainder of current page. |
| 1375 Address limit = NewSpacePage::FromLimit(top)->area_end(); | 1419 Address limit = NewSpacePage::FromLimit(top)->area_end(); |
| 1376 if (heap()->gc_state() == Heap::SCAVENGE) { | 1420 if (heap()->gc_state() == Heap::SCAVENGE) { |
| 1377 heap()->promotion_queue()->SetNewLimit(limit); | 1421 heap()->promotion_queue()->SetNewLimit(limit); |
| 1378 } | 1422 } |
| 1379 | 1423 |
| 1380 int remaining_in_page = static_cast<int>(limit - top); | 1424 int remaining_in_page = static_cast<int>(limit - top); |
| 1381 heap()->CreateFillerObjectAt(top, remaining_in_page); | 1425 heap()->CreateFillerObjectAt(top, remaining_in_page); |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1465 CHECK_EQ(from_space_.id(), kFromSpace); | 1509 CHECK_EQ(from_space_.id(), kFromSpace); |
| 1466 CHECK_EQ(to_space_.id(), kToSpace); | 1510 CHECK_EQ(to_space_.id(), kToSpace); |
| 1467 from_space_.Verify(); | 1511 from_space_.Verify(); |
| 1468 to_space_.Verify(); | 1512 to_space_.Verify(); |
| 1469 } | 1513 } |
| 1470 #endif | 1514 #endif |
| 1471 | 1515 |
| 1472 // ----------------------------------------------------------------------------- | 1516 // ----------------------------------------------------------------------------- |
| 1473 // SemiSpace implementation | 1517 // SemiSpace implementation |
| 1474 | 1518 |
| 1475 void SemiSpace::SetUp(Address start, int initial_capacity, | 1519 void SemiSpace::SetUp(Address start, int initial_capacity, int target_capacity, |
| 1476 int maximum_capacity) { | 1520 int maximum_capacity) { |
| 1477 // Creates a space in the young generation. The constructor does not | 1521 // Creates a space in the young generation. The constructor does not |
| 1478 // allocate memory from the OS. A SemiSpace is given a contiguous chunk of | 1522 // allocate memory from the OS. A SemiSpace is given a contiguous chunk of |
| 1479 // memory of size 'capacity' when set up, and does not grow or shrink | 1523 // memory of size 'capacity' when set up, and does not grow or shrink |
| 1480 // otherwise. In the mark-compact collector, the memory region of the from | 1524 // otherwise. In the mark-compact collector, the memory region of the from |
| 1481 // space is used as the marking stack. It requires contiguous memory | 1525 // space is used as the marking stack. It requires contiguous memory |
| 1482 // addresses. | 1526 // addresses. |
| 1483 DCHECK(maximum_capacity >= Page::kPageSize); | 1527 DCHECK(maximum_capacity >= Page::kPageSize); |
| 1528 DCHECK(initial_capacity <= target_capacity); |
| 1529 DCHECK(target_capacity <= maximum_capacity); |
| 1484 initial_total_capacity_ = RoundDown(initial_capacity, Page::kPageSize); | 1530 initial_total_capacity_ = RoundDown(initial_capacity, Page::kPageSize); |
| 1485 total_capacity_ = initial_capacity; | 1531 total_capacity_ = initial_capacity; |
| 1532 target_capacity_ = RoundDown(target_capacity, Page::kPageSize); |
| 1486 maximum_total_capacity_ = RoundDown(maximum_capacity, Page::kPageSize); | 1533 maximum_total_capacity_ = RoundDown(maximum_capacity, Page::kPageSize); |
| 1487 maximum_committed_ = 0; | 1534 maximum_committed_ = 0; |
| 1488 committed_ = false; | 1535 committed_ = false; |
| 1489 start_ = start; | 1536 start_ = start; |
| 1490 address_mask_ = ~(maximum_capacity - 1); | 1537 address_mask_ = ~(maximum_capacity - 1); |
| 1491 object_mask_ = address_mask_ | kHeapObjectTagMask; | 1538 object_mask_ = address_mask_ | kHeapObjectTagMask; |
| 1492 object_expected_ = reinterpret_cast<uintptr_t>(start) | kHeapObjectTag; | 1539 object_expected_ = reinterpret_cast<uintptr_t>(start) | kHeapObjectTag; |
| 1493 age_mark_ = start_; | 1540 age_mark_ = start_; |
| 1494 } | 1541 } |
| 1495 | 1542 |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1604 anchor()->set_prev_page(new_last_page); | 1651 anchor()->set_prev_page(new_last_page); |
| 1605 DCHECK((current_page_ >= first_page()) && (current_page_ <= new_last_page)); | 1652 DCHECK((current_page_ >= first_page()) && (current_page_ <= new_last_page)); |
| 1606 } | 1653 } |
| 1607 | 1654 |
| 1608 SetCapacity(new_capacity); | 1655 SetCapacity(new_capacity); |
| 1609 | 1656 |
| 1610 return true; | 1657 return true; |
| 1611 } | 1658 } |
| 1612 | 1659 |
| 1613 | 1660 |
| 1661 bool SemiSpace::SetTotalCapacity(int new_capacity) { |
| 1662 CHECK(!is_committed()); |
| 1663 if (new_capacity >= initial_total_capacity_ && |
| 1664 new_capacity <= maximum_total_capacity_) { |
| 1665 total_capacity_ = new_capacity; |
| 1666 return true; |
| 1667 } |
| 1668 return false; |
| 1669 } |
| 1670 |
| 1671 |
| 1614 void SemiSpace::FlipPages(intptr_t flags, intptr_t mask) { | 1672 void SemiSpace::FlipPages(intptr_t flags, intptr_t mask) { |
| 1615 anchor_.set_owner(this); | 1673 anchor_.set_owner(this); |
| 1616 // Fixup back-pointers to anchor. Address of anchor changes | 1674 // Fixup back-pointers to anchor. Address of anchor changes |
| 1617 // when we swap. | 1675 // when we swap. |
| 1618 anchor_.prev_page()->set_next_page(&anchor_); | 1676 anchor_.prev_page()->set_next_page(&anchor_); |
| 1619 anchor_.next_page()->set_prev_page(&anchor_); | 1677 anchor_.next_page()->set_prev_page(&anchor_); |
| 1620 | 1678 |
| 1621 bool becomes_to_space = (id_ == kFromSpace); | 1679 bool becomes_to_space = (id_ == kFromSpace); |
| 1622 id_ = becomes_to_space ? kToSpace : kFromSpace; | 1680 id_ = becomes_to_space ? kToSpace : kFromSpace; |
| 1623 NewSpacePage* page = anchor_.next_page(); | 1681 NewSpacePage* page = anchor_.next_page(); |
| (...skipping 1487 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3111 object->ShortPrint(); | 3169 object->ShortPrint(); |
| 3112 PrintF("\n"); | 3170 PrintF("\n"); |
| 3113 } | 3171 } |
| 3114 printf(" --------------------------------------\n"); | 3172 printf(" --------------------------------------\n"); |
| 3115 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); | 3173 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); |
| 3116 } | 3174 } |
| 3117 | 3175 |
| 3118 #endif // DEBUG | 3176 #endif // DEBUG |
| 3119 } | 3177 } |
| 3120 } // namespace v8::internal | 3178 } // namespace v8::internal |
| OLD | NEW |