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 479 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
490 | 490 |
491 MemoryChunk* MemoryAllocator::AllocateChunk(intptr_t body_size, | 491 MemoryChunk* MemoryAllocator::AllocateChunk(intptr_t body_size, |
492 Executability executable, | 492 Executability executable, |
493 Space* owner) { | 493 Space* owner) { |
494 size_t chunk_size; | 494 size_t chunk_size; |
495 Heap* heap = isolate_->heap(); | 495 Heap* heap = isolate_->heap(); |
496 Address base = NULL; | 496 Address base = NULL; |
497 VirtualMemory reservation; | 497 VirtualMemory reservation; |
498 Address area_start = NULL; | 498 Address area_start = NULL; |
499 Address area_end = NULL; | 499 Address area_end = NULL; |
| 500 |
| 501 // Zapping should only occur in debug mode or in release with verify_heap on |
| 502 #ifdef DEBUG |
| 503 bool zap_blocks = true; |
| 504 #else |
| 505 bool zap_blocks = FLAG_verify_heap; |
| 506 #endif |
| 507 |
500 if (executable == EXECUTABLE) { | 508 if (executable == EXECUTABLE) { |
501 chunk_size = RoundUp(CodePageAreaStartOffset() + body_size, | 509 chunk_size = RoundUp(CodePageAreaStartOffset() + body_size, |
502 OS::CommitPageSize()) + CodePageGuardSize(); | 510 OS::CommitPageSize()) + CodePageGuardSize(); |
503 | 511 |
504 // Check executable memory limit. | 512 // Check executable memory limit. |
505 if (size_executable_ + chunk_size > capacity_executable_) { | 513 if (size_executable_ + chunk_size > capacity_executable_) { |
506 LOG(isolate_, | 514 LOG(isolate_, |
507 StringEvent("MemoryAllocator::AllocateRawMemory", | 515 StringEvent("MemoryAllocator::AllocateRawMemory", |
508 "V8 Executable Allocation capacity exceeded")); | 516 "V8 Executable Allocation capacity exceeded")); |
509 return NULL; | 517 return NULL; |
(...skipping 12 matching lines...) Expand all Loading... |
522 } else { | 530 } else { |
523 base = AllocateAlignedMemory(chunk_size, | 531 base = AllocateAlignedMemory(chunk_size, |
524 MemoryChunk::kAlignment, | 532 MemoryChunk::kAlignment, |
525 executable, | 533 executable, |
526 &reservation); | 534 &reservation); |
527 if (base == NULL) return NULL; | 535 if (base == NULL) return NULL; |
528 // Update executable memory size. | 536 // Update executable memory size. |
529 size_executable_ += reservation.size(); | 537 size_executable_ += reservation.size(); |
530 } | 538 } |
531 | 539 |
532 #ifdef DEBUG | 540 if (zap_blocks) { |
533 ZapBlock(base, CodePageGuardStartOffset()); | 541 ZapBlock(base, CodePageGuardStartOffset()); |
534 ZapBlock(base + CodePageAreaStartOffset(), body_size); | 542 ZapBlock(base + CodePageAreaStartOffset(), body_size); |
535 #endif | 543 } |
| 544 |
536 area_start = base + CodePageAreaStartOffset(); | 545 area_start = base + CodePageAreaStartOffset(); |
537 area_end = area_start + body_size; | 546 area_end = area_start + body_size; |
538 } else { | 547 } else { |
539 chunk_size = MemoryChunk::kObjectStartOffset + body_size; | 548 chunk_size = MemoryChunk::kObjectStartOffset + body_size; |
540 base = AllocateAlignedMemory(chunk_size, | 549 base = AllocateAlignedMemory(chunk_size, |
541 MemoryChunk::kAlignment, | 550 MemoryChunk::kAlignment, |
542 executable, | 551 executable, |
543 &reservation); | 552 &reservation); |
544 | 553 |
545 if (base == NULL) return NULL; | 554 if (base == NULL) return NULL; |
546 | 555 |
547 #ifdef DEBUG | 556 if (zap_blocks) { |
548 ZapBlock(base, chunk_size); | 557 ZapBlock(base, chunk_size); |
549 #endif | 558 } |
550 | 559 |
551 area_start = base + Page::kObjectStartOffset; | 560 area_start = base + Page::kObjectStartOffset; |
552 area_end = base + chunk_size; | 561 area_end = base + chunk_size; |
553 } | 562 } |
554 | 563 |
555 isolate_->counters()->memory_allocated()-> | 564 isolate_->counters()->memory_allocated()-> |
556 Increment(static_cast<int>(chunk_size)); | 565 Increment(static_cast<int>(chunk_size)); |
557 | 566 |
558 LOG(isolate_, NewEvent("MemoryChunk", base, chunk_size)); | 567 LOG(isolate_, NewEvent("MemoryChunk", base, chunk_size)); |
559 if (owner != NULL) { | 568 if (owner != NULL) { |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
615 chunk->size(), | 624 chunk->size(), |
616 chunk->executable()); | 625 chunk->executable()); |
617 } | 626 } |
618 } | 627 } |
619 | 628 |
620 | 629 |
621 bool MemoryAllocator::CommitBlock(Address start, | 630 bool MemoryAllocator::CommitBlock(Address start, |
622 size_t size, | 631 size_t size, |
623 Executability executable) { | 632 Executability executable) { |
624 if (!VirtualMemory::CommitRegion(start, size, executable)) return false; | 633 if (!VirtualMemory::CommitRegion(start, size, executable)) return false; |
625 #ifdef DEBUG | 634 |
626 ZapBlock(start, size); | 635 // In release mode, only zap the block if verify heap is on. |
| 636 #ifndef DEBUG |
| 637 if (FLAG_verify_heap) { |
627 #endif | 638 #endif |
| 639 ZapBlock(start, size); |
| 640 #ifndef DEBUG |
| 641 } |
| 642 #endif |
| 643 |
628 isolate_->counters()->memory_allocated()->Increment(static_cast<int>(size)); | 644 isolate_->counters()->memory_allocated()->Increment(static_cast<int>(size)); |
629 return true; | 645 return true; |
630 } | 646 } |
631 | 647 |
632 | 648 |
633 bool MemoryAllocator::UncommitBlock(Address start, size_t size) { | 649 bool MemoryAllocator::UncommitBlock(Address start, size_t size) { |
634 if (!VirtualMemory::UncommitRegion(start, size)) return false; | 650 if (!VirtualMemory::UncommitRegion(start, size)) return false; |
635 isolate_->counters()->memory_allocated()->Decrement(static_cast<int>(size)); | 651 isolate_->counters()->memory_allocated()->Decrement(static_cast<int>(size)); |
636 return true; | 652 return true; |
637 } | 653 } |
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
979 } | 995 } |
980 heap()->FreeQueuedChunks(); | 996 heap()->FreeQueuedChunks(); |
981 } | 997 } |
982 | 998 |
983 | 999 |
984 #ifdef DEBUG | 1000 #ifdef DEBUG |
985 void PagedSpace::Print() { } | 1001 void PagedSpace::Print() { } |
986 #endif | 1002 #endif |
987 | 1003 |
988 | 1004 |
989 #ifdef DEBUG | |
990 void PagedSpace::Verify(ObjectVisitor* visitor) { | 1005 void PagedSpace::Verify(ObjectVisitor* visitor) { |
991 // We can only iterate over the pages if they were swept precisely. | 1006 // We can only iterate over the pages if they were swept precisely. |
992 if (was_swept_conservatively_) return; | 1007 if (was_swept_conservatively_) return; |
993 | 1008 |
994 bool allocation_pointer_found_in_space = | 1009 bool allocation_pointer_found_in_space = |
995 (allocation_info_.top == allocation_info_.limit); | 1010 (allocation_info_.top == allocation_info_.limit); |
996 PageIterator page_iterator(this); | 1011 PageIterator page_iterator(this); |
997 while (page_iterator.has_next()) { | 1012 while (page_iterator.has_next()) { |
998 Page* page = page_iterator.next(); | 1013 Page* page = page_iterator.next(); |
999 ASSERT(page->owner() == this); | 1014 CHECK(page->owner() == this); |
1000 if (page == Page::FromAllocationTop(allocation_info_.top)) { | 1015 if (page == Page::FromAllocationTop(allocation_info_.top)) { |
1001 allocation_pointer_found_in_space = true; | 1016 allocation_pointer_found_in_space = true; |
1002 } | 1017 } |
1003 ASSERT(page->WasSweptPrecisely()); | 1018 CHECK(page->WasSweptPrecisely()); |
1004 HeapObjectIterator it(page, NULL); | 1019 HeapObjectIterator it(page, NULL); |
1005 Address end_of_previous_object = page->area_start(); | 1020 Address end_of_previous_object = page->area_start(); |
1006 Address top = page->area_end(); | 1021 Address top = page->area_end(); |
1007 int black_size = 0; | 1022 int black_size = 0; |
1008 for (HeapObject* object = it.Next(); object != NULL; object = it.Next()) { | 1023 for (HeapObject* object = it.Next(); object != NULL; object = it.Next()) { |
1009 ASSERT(end_of_previous_object <= object->address()); | 1024 CHECK(end_of_previous_object <= object->address()); |
1010 | 1025 |
1011 // The first word should be a map, and we expect all map pointers to | 1026 // The first word should be a map, and we expect all map pointers to |
1012 // be in map space. | 1027 // be in map space. |
1013 Map* map = object->map(); | 1028 Map* map = object->map(); |
1014 ASSERT(map->IsMap()); | 1029 CHECK(map->IsMap()); |
1015 ASSERT(heap()->map_space()->Contains(map)); | 1030 CHECK(heap()->map_space()->Contains(map)); |
1016 | 1031 |
1017 // Perform space-specific object verification. | 1032 // Perform space-specific object verification. |
1018 VerifyObject(object); | 1033 VerifyObject(object); |
1019 | 1034 |
| 1035 #ifdef DEBUG |
1020 // The object itself should look OK. | 1036 // The object itself should look OK. |
1021 object->Verify(); | 1037 object->Verify(); |
| 1038 #endif |
1022 | 1039 |
1023 // All the interior pointers should be contained in the heap. | 1040 // All the interior pointers should be contained in the heap. |
1024 int size = object->Size(); | 1041 int size = object->Size(); |
1025 object->IterateBody(map->instance_type(), size, visitor); | 1042 object->IterateBody(map->instance_type(), size, visitor); |
1026 if (Marking::IsBlack(Marking::MarkBitFrom(object))) { | 1043 if (Marking::IsBlack(Marking::MarkBitFrom(object))) { |
1027 black_size += size; | 1044 black_size += size; |
1028 } | 1045 } |
1029 | 1046 |
1030 ASSERT(object->address() + size <= top); | 1047 CHECK(object->address() + size <= top); |
1031 end_of_previous_object = object->address() + size; | 1048 end_of_previous_object = object->address() + size; |
1032 } | 1049 } |
1033 ASSERT_LE(black_size, page->LiveBytes()); | 1050 CHECK_LE(black_size, page->LiveBytes()); |
1034 } | 1051 } |
1035 ASSERT(allocation_pointer_found_in_space); | 1052 CHECK(allocation_pointer_found_in_space); |
1036 } | 1053 } |
1037 #endif | |
1038 | |
1039 | 1054 |
1040 // ----------------------------------------------------------------------------- | 1055 // ----------------------------------------------------------------------------- |
1041 // NewSpace implementation | 1056 // NewSpace implementation |
1042 | 1057 |
1043 | 1058 |
1044 bool NewSpace::SetUp(int reserved_semispace_capacity, | 1059 bool NewSpace::SetUp(int reserved_semispace_capacity, |
1045 int maximum_semispace_capacity) { | 1060 int maximum_semispace_capacity) { |
1046 // Set up new space based on the preallocated memory block defined by | 1061 // Set up new space based on the preallocated memory block defined by |
1047 // start and size. The provided space is divided into two semi-spaces. | 1062 // start and size. The provided space is divided into two semi-spaces. |
1048 // To support fast containment testing in the new space, the size of | 1063 // To support fast containment testing in the new space, the size of |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1252 heap()->incremental_marking()->Step( | 1267 heap()->incremental_marking()->Step( |
1253 bytes_allocated, IncrementalMarking::GC_VIA_STACK_GUARD); | 1268 bytes_allocated, IncrementalMarking::GC_VIA_STACK_GUARD); |
1254 top_on_previous_step_ = to_space_.page_low(); | 1269 top_on_previous_step_ = to_space_.page_low(); |
1255 return AllocateRaw(size_in_bytes); | 1270 return AllocateRaw(size_in_bytes); |
1256 } else { | 1271 } else { |
1257 return Failure::RetryAfterGC(); | 1272 return Failure::RetryAfterGC(); |
1258 } | 1273 } |
1259 } | 1274 } |
1260 | 1275 |
1261 | 1276 |
1262 #ifdef DEBUG | 1277 |
1263 // We do not use the SemiSpaceIterator because verification doesn't assume | 1278 // We do not use the SemiSpaceIterator because verification doesn't assume |
1264 // that it works (it depends on the invariants we are checking). | 1279 // that it works (it depends on the invariants we are checking). |
1265 void NewSpace::Verify() { | 1280 void NewSpace::Verify() { |
1266 // The allocation pointer should be in the space or at the very end. | 1281 // The allocation pointer should be in the space or at the very end. |
1267 ASSERT_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); | 1282 ASSERT_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); |
1268 | 1283 |
1269 // There should be objects packed in from the low address up to the | 1284 // There should be objects packed in from the low address up to the |
1270 // allocation pointer. | 1285 // allocation pointer. |
1271 Address current = to_space_.first_page()->area_start(); | 1286 Address current = to_space_.first_page()->area_start(); |
1272 CHECK_EQ(current, to_space_.space_start()); | 1287 CHECK_EQ(current, to_space_.space_start()); |
1273 | 1288 |
1274 while (current != top()) { | 1289 while (current != top()) { |
1275 if (!NewSpacePage::IsAtEnd(current)) { | 1290 if (!NewSpacePage::IsAtEnd(current)) { |
1276 // The allocation pointer should not be in the middle of an object. | 1291 // The allocation pointer should not be in the middle of an object. |
1277 CHECK(!NewSpacePage::FromLimit(current)->ContainsLimit(top()) || | 1292 CHECK(!NewSpacePage::FromLimit(current)->ContainsLimit(top()) || |
1278 current < top()); | 1293 current < top()); |
1279 | 1294 |
1280 HeapObject* object = HeapObject::FromAddress(current); | 1295 HeapObject* object = HeapObject::FromAddress(current); |
1281 | 1296 |
1282 // The first word should be a map, and we expect all map pointers to | 1297 // The first word should be a map, and we expect all map pointers to |
1283 // be in map space. | 1298 // be in map space. |
1284 Map* map = object->map(); | 1299 Map* map = object->map(); |
1285 CHECK(map->IsMap()); | 1300 CHECK(map->IsMap()); |
1286 CHECK(heap()->map_space()->Contains(map)); | 1301 CHECK(heap()->map_space()->Contains(map)); |
1287 | 1302 |
1288 // The object should not be code or a map. | 1303 // The object should not be code or a map. |
1289 CHECK(!object->IsMap()); | 1304 CHECK(!object->IsMap()); |
1290 CHECK(!object->IsCode()); | 1305 CHECK(!object->IsCode()); |
1291 | 1306 |
| 1307 #ifdef DEBUG |
1292 // The object itself should look OK. | 1308 // The object itself should look OK. |
1293 object->Verify(); | 1309 object->Verify(); |
| 1310 #endif |
1294 | 1311 |
1295 // All the interior pointers should be contained in the heap. | 1312 // All the interior pointers should be contained in the heap. |
1296 VerifyPointersVisitor visitor; | 1313 VerifyPointersVisitor visitor; |
1297 int size = object->Size(); | 1314 int size = object->Size(); |
1298 object->IterateBody(map->instance_type(), size, &visitor); | 1315 object->IterateBody(map->instance_type(), size, &visitor); |
1299 | 1316 |
1300 current += size; | 1317 current += size; |
1301 } else { | 1318 } else { |
1302 // At end of page, switch to next page. | 1319 // At end of page, switch to next page. |
1303 NewSpacePage* page = NewSpacePage::FromLimit(current)->next_page(); | 1320 NewSpacePage* page = NewSpacePage::FromLimit(current)->next_page(); |
1304 // Next page should be valid. | 1321 // Next page should be valid. |
1305 CHECK(!page->is_anchor()); | 1322 CHECK(!page->is_anchor()); |
1306 current = page->area_start(); | 1323 current = page->area_start(); |
1307 } | 1324 } |
1308 } | 1325 } |
1309 | 1326 |
1310 // Check semi-spaces. | 1327 // Check semi-spaces. |
1311 ASSERT_EQ(from_space_.id(), kFromSpace); | 1328 CHECK_EQ(from_space_.id(), kFromSpace); |
1312 ASSERT_EQ(to_space_.id(), kToSpace); | 1329 CHECK_EQ(to_space_.id(), kToSpace); |
1313 from_space_.Verify(); | 1330 from_space_.Verify(); |
1314 to_space_.Verify(); | 1331 to_space_.Verify(); |
1315 } | 1332 } |
1316 #endif | 1333 |
1317 | 1334 |
1318 // ----------------------------------------------------------------------------- | 1335 // ----------------------------------------------------------------------------- |
1319 // SemiSpace implementation | 1336 // SemiSpace implementation |
1320 | 1337 |
1321 void SemiSpace::SetUp(Address start, | 1338 void SemiSpace::SetUp(Address start, |
1322 int initial_capacity, | 1339 int initial_capacity, |
1323 int maximum_capacity) { | 1340 int maximum_capacity) { |
1324 // Creates a space in the young generation. The constructor does not | 1341 // Creates a space in the young generation. The constructor does not |
1325 // allocate memory from the OS. A SemiSpace is given a contiguous chunk of | 1342 // allocate memory from the OS. A SemiSpace is given a contiguous chunk of |
1326 // memory of size 'capacity' when set up, and does not grow or shrink | 1343 // memory of size 'capacity' when set up, and does not grow or shrink |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1518 // Mark all pages up to the one containing mark. | 1535 // Mark all pages up to the one containing mark. |
1519 NewSpacePageIterator it(space_start(), mark); | 1536 NewSpacePageIterator it(space_start(), mark); |
1520 while (it.has_next()) { | 1537 while (it.has_next()) { |
1521 it.next()->SetFlag(MemoryChunk::NEW_SPACE_BELOW_AGE_MARK); | 1538 it.next()->SetFlag(MemoryChunk::NEW_SPACE_BELOW_AGE_MARK); |
1522 } | 1539 } |
1523 } | 1540 } |
1524 | 1541 |
1525 | 1542 |
1526 #ifdef DEBUG | 1543 #ifdef DEBUG |
1527 void SemiSpace::Print() { } | 1544 void SemiSpace::Print() { } |
1528 | 1545 #endif |
1529 | 1546 |
1530 void SemiSpace::Verify() { | 1547 void SemiSpace::Verify() { |
1531 bool is_from_space = (id_ == kFromSpace); | 1548 bool is_from_space = (id_ == kFromSpace); |
1532 NewSpacePage* page = anchor_.next_page(); | 1549 NewSpacePage* page = anchor_.next_page(); |
1533 CHECK(anchor_.semi_space() == this); | 1550 CHECK(anchor_.semi_space() == this); |
1534 while (page != &anchor_) { | 1551 while (page != &anchor_) { |
1535 CHECK(page->semi_space() == this); | 1552 CHECK(page->semi_space() == this); |
1536 CHECK(page->InNewSpace()); | 1553 CHECK(page->InNewSpace()); |
1537 CHECK(page->IsFlagSet(is_from_space ? MemoryChunk::IN_FROM_SPACE | 1554 CHECK(page->IsFlagSet(is_from_space ? MemoryChunk::IN_FROM_SPACE |
1538 : MemoryChunk::IN_TO_SPACE)); | 1555 : MemoryChunk::IN_TO_SPACE)); |
(...skipping 11 matching lines...) Expand all Loading... |
1550 } | 1567 } |
1551 // TODO(gc): Check that the live_bytes_count_ field matches the | 1568 // TODO(gc): Check that the live_bytes_count_ field matches the |
1552 // black marking on the page (if we make it match in new-space). | 1569 // black marking on the page (if we make it match in new-space). |
1553 } | 1570 } |
1554 CHECK(page->IsFlagSet(MemoryChunk::SCAN_ON_SCAVENGE)); | 1571 CHECK(page->IsFlagSet(MemoryChunk::SCAN_ON_SCAVENGE)); |
1555 CHECK(page->prev_page()->next_page() == page); | 1572 CHECK(page->prev_page()->next_page() == page); |
1556 page = page->next_page(); | 1573 page = page->next_page(); |
1557 } | 1574 } |
1558 } | 1575 } |
1559 | 1576 |
1560 | 1577 #ifdef DEBUG |
1561 void SemiSpace::AssertValidRange(Address start, Address end) { | 1578 void SemiSpace::AssertValidRange(Address start, Address end) { |
1562 // Addresses belong to same semi-space | 1579 // Addresses belong to same semi-space |
1563 NewSpacePage* page = NewSpacePage::FromLimit(start); | 1580 NewSpacePage* page = NewSpacePage::FromLimit(start); |
1564 NewSpacePage* end_page = NewSpacePage::FromLimit(end); | 1581 NewSpacePage* end_page = NewSpacePage::FromLimit(end); |
1565 SemiSpace* space = page->semi_space(); | 1582 SemiSpace* space = page->semi_space(); |
1566 CHECK_EQ(space, end_page->semi_space()); | 1583 CHECK_EQ(space, end_page->semi_space()); |
1567 // Start address is before end address, either on same page, | 1584 // Start address is before end address, either on same page, |
1568 // or end address is on a later page in the linked list of | 1585 // or end address is on a later page in the linked list of |
1569 // semi-space pages. | 1586 // semi-space pages. |
1570 if (page == end_page) { | 1587 if (page == end_page) { |
(...skipping 974 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2545 accounting_stats_.AllocateBytes(free_list_.available()); | 2562 accounting_stats_.AllocateBytes(free_list_.available()); |
2546 | 2563 |
2547 // Clear the free list before a full GC---it will be rebuilt afterward. | 2564 // Clear the free list before a full GC---it will be rebuilt afterward. |
2548 free_list_.Reset(); | 2565 free_list_.Reset(); |
2549 } | 2566 } |
2550 | 2567 |
2551 | 2568 |
2552 // ----------------------------------------------------------------------------- | 2569 // ----------------------------------------------------------------------------- |
2553 // MapSpace implementation | 2570 // MapSpace implementation |
2554 | 2571 |
2555 #ifdef DEBUG | |
2556 void MapSpace::VerifyObject(HeapObject* object) { | 2572 void MapSpace::VerifyObject(HeapObject* object) { |
2557 // The object should be a map or a free-list node. | 2573 // The object should be a map or a free-list node. |
2558 ASSERT(object->IsMap() || object->IsFreeSpace()); | 2574 CHECK(object->IsMap() || object->IsFreeSpace()); |
2559 } | 2575 } |
2560 #endif | |
2561 | 2576 |
2562 | 2577 |
2563 // ----------------------------------------------------------------------------- | 2578 // ----------------------------------------------------------------------------- |
2564 // GlobalPropertyCellSpace implementation | 2579 // GlobalPropertyCellSpace implementation |
2565 | 2580 |
2566 #ifdef DEBUG | |
2567 void CellSpace::VerifyObject(HeapObject* object) { | 2581 void CellSpace::VerifyObject(HeapObject* object) { |
2568 // The object should be a global object property cell or a free-list node. | 2582 // The object should be a global object property cell or a free-list node. |
2569 ASSERT(object->IsJSGlobalPropertyCell() || | 2583 CHECK(object->IsJSGlobalPropertyCell() || |
2570 object->map() == heap()->two_pointer_filler_map()); | 2584 object->map() == heap()->two_pointer_filler_map()); |
2571 } | 2585 } |
2572 #endif | |
2573 | 2586 |
2574 | 2587 |
2575 // ----------------------------------------------------------------------------- | 2588 // ----------------------------------------------------------------------------- |
2576 // LargeObjectIterator | 2589 // LargeObjectIterator |
2577 | 2590 |
2578 LargeObjectIterator::LargeObjectIterator(LargeObjectSpace* space) { | 2591 LargeObjectIterator::LargeObjectIterator(LargeObjectSpace* space) { |
2579 current_ = space->first_page_; | 2592 current_ = space->first_page_; |
2580 size_func_ = NULL; | 2593 size_func_ = NULL; |
2581 } | 2594 } |
2582 | 2595 |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2672 for (uintptr_t key = base; key <= limit; key++) { | 2685 for (uintptr_t key = base; key <= limit; key++) { |
2673 HashMap::Entry* entry = chunk_map_.Lookup(reinterpret_cast<void*>(key), | 2686 HashMap::Entry* entry = chunk_map_.Lookup(reinterpret_cast<void*>(key), |
2674 static_cast<uint32_t>(key), | 2687 static_cast<uint32_t>(key), |
2675 true); | 2688 true); |
2676 ASSERT(entry != NULL); | 2689 ASSERT(entry != NULL); |
2677 entry->value = page; | 2690 entry->value = page; |
2678 } | 2691 } |
2679 | 2692 |
2680 HeapObject* object = page->GetObject(); | 2693 HeapObject* object = page->GetObject(); |
2681 | 2694 |
2682 #ifdef DEBUG | 2695 #ifndef DEBUG |
2683 // Make the object consistent so the heap can be vefified in OldSpaceStep. | 2696 if (FLAG_verify_heap) { |
2684 reinterpret_cast<Object**>(object->address())[0] = | 2697 #endif |
2685 heap()->fixed_array_map(); | 2698 // Make the object consistent so the heap can be vefified in OldSpaceStep. |
2686 reinterpret_cast<Object**>(object->address())[1] = Smi::FromInt(0); | 2699 // We only need to do this in debug builds or if verify_heap is on. |
| 2700 reinterpret_cast<Object**>(object->address())[0] = |
| 2701 heap()->fixed_array_map(); |
| 2702 reinterpret_cast<Object**>(object->address())[1] = Smi::FromInt(0); |
| 2703 #ifndef DEBUG |
| 2704 } |
2687 #endif | 2705 #endif |
2688 | 2706 |
2689 heap()->incremental_marking()->OldSpaceStep(object_size); | 2707 heap()->incremental_marking()->OldSpaceStep(object_size); |
2690 return object; | 2708 return object; |
2691 } | 2709 } |
2692 | 2710 |
2693 | 2711 |
2694 // GC support | 2712 // GC support |
2695 MaybeObject* LargeObjectSpace::FindObject(Address a) { | 2713 MaybeObject* LargeObjectSpace::FindObject(Address a) { |
2696 LargePage* page = FindPage(a); | 2714 LargePage* page = FindPage(a); |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2776 MemoryChunk* chunk = MemoryChunk::FromAddress(address); | 2794 MemoryChunk* chunk = MemoryChunk::FromAddress(address); |
2777 | 2795 |
2778 bool owned = (chunk->owner() == this); | 2796 bool owned = (chunk->owner() == this); |
2779 | 2797 |
2780 SLOW_ASSERT(!owned || !FindObject(address)->IsFailure()); | 2798 SLOW_ASSERT(!owned || !FindObject(address)->IsFailure()); |
2781 | 2799 |
2782 return owned; | 2800 return owned; |
2783 } | 2801 } |
2784 | 2802 |
2785 | 2803 |
2786 #ifdef DEBUG | |
2787 // We do not assume that the large object iterator works, because it depends | 2804 // We do not assume that the large object iterator works, because it depends |
2788 // on the invariants we are checking during verification. | 2805 // on the invariants we are checking during verification. |
2789 void LargeObjectSpace::Verify() { | 2806 void LargeObjectSpace::Verify() { |
2790 for (LargePage* chunk = first_page_; | 2807 for (LargePage* chunk = first_page_; |
2791 chunk != NULL; | 2808 chunk != NULL; |
2792 chunk = chunk->next_page()) { | 2809 chunk = chunk->next_page()) { |
2793 // Each chunk contains an object that starts at the large object page's | 2810 // Each chunk contains an object that starts at the large object page's |
2794 // object area start. | 2811 // object area start. |
2795 HeapObject* object = chunk->GetObject(); | 2812 HeapObject* object = chunk->GetObject(); |
2796 Page* page = Page::FromAddress(object->address()); | 2813 Page* page = Page::FromAddress(object->address()); |
2797 ASSERT(object->address() == page->area_start()); | 2814 CHECK(object->address() == page->area_start()); |
2798 | 2815 |
2799 // The first word should be a map, and we expect all map pointers to be | 2816 // The first word should be a map, and we expect all map pointers to be |
2800 // in map space. | 2817 // in map space. |
2801 Map* map = object->map(); | 2818 Map* map = object->map(); |
2802 ASSERT(map->IsMap()); | 2819 CHECK(map->IsMap()); |
2803 ASSERT(heap()->map_space()->Contains(map)); | 2820 CHECK(heap()->map_space()->Contains(map)); |
2804 | 2821 |
2805 // We have only code, sequential strings, external strings | 2822 // We have only code, sequential strings, external strings |
2806 // (sequential strings that have been morphed into external | 2823 // (sequential strings that have been morphed into external |
2807 // strings), fixed arrays, and byte arrays in large object space. | 2824 // strings), fixed arrays, and byte arrays in large object space. |
2808 ASSERT(object->IsCode() || object->IsSeqString() || | 2825 CHECK(object->IsCode() || object->IsSeqString() || |
2809 object->IsExternalString() || object->IsFixedArray() || | 2826 object->IsExternalString() || object->IsFixedArray() || |
2810 object->IsFixedDoubleArray() || object->IsByteArray()); | 2827 object->IsFixedDoubleArray() || object->IsByteArray()); |
2811 | 2828 |
| 2829 #ifdef DEBUG |
2812 // The object itself should look OK. | 2830 // The object itself should look OK. |
2813 object->Verify(); | 2831 object->Verify(); |
| 2832 #endif |
2814 | 2833 |
2815 // Byte arrays and strings don't have interior pointers. | 2834 // Byte arrays and strings don't have interior pointers. |
2816 if (object->IsCode()) { | 2835 if (object->IsCode()) { |
2817 VerifyPointersVisitor code_visitor; | 2836 VerifyPointersVisitor code_visitor; |
2818 object->IterateBody(map->instance_type(), | 2837 object->IterateBody(map->instance_type(), |
2819 object->Size(), | 2838 object->Size(), |
2820 &code_visitor); | 2839 &code_visitor); |
2821 } else if (object->IsFixedArray()) { | 2840 } else if (object->IsFixedArray()) { |
2822 FixedArray* array = FixedArray::cast(object); | 2841 FixedArray* array = FixedArray::cast(object); |
2823 for (int j = 0; j < array->length(); j++) { | 2842 for (int j = 0; j < array->length(); j++) { |
2824 Object* element = array->get(j); | 2843 Object* element = array->get(j); |
2825 if (element->IsHeapObject()) { | 2844 if (element->IsHeapObject()) { |
2826 HeapObject* element_object = HeapObject::cast(element); | 2845 HeapObject* element_object = HeapObject::cast(element); |
2827 ASSERT(heap()->Contains(element_object)); | 2846 CHECK(heap()->Contains(element_object)); |
2828 ASSERT(element_object->map()->IsMap()); | 2847 CHECK(element_object->map()->IsMap()); |
2829 } | 2848 } |
2830 } | 2849 } |
2831 } | 2850 } |
2832 } | 2851 } |
2833 } | 2852 } |
2834 | 2853 |
2835 | 2854 #ifdef DEBUG |
2836 void LargeObjectSpace::Print() { | 2855 void LargeObjectSpace::Print() { |
2837 LargeObjectIterator it(this); | 2856 LargeObjectIterator it(this); |
2838 for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) { | 2857 for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) { |
2839 obj->Print(); | 2858 obj->Print(); |
2840 } | 2859 } |
2841 } | 2860 } |
2842 | 2861 |
2843 | 2862 |
2844 void LargeObjectSpace::ReportStatistics() { | 2863 void LargeObjectSpace::ReportStatistics() { |
2845 PrintF(" size: %" V8_PTR_PREFIX "d\n", size_); | 2864 PrintF(" size: %" V8_PTR_PREFIX "d\n", size_); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2888 object->ShortPrint(); | 2907 object->ShortPrint(); |
2889 PrintF("\n"); | 2908 PrintF("\n"); |
2890 } | 2909 } |
2891 printf(" --------------------------------------\n"); | 2910 printf(" --------------------------------------\n"); |
2892 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); | 2911 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); |
2893 } | 2912 } |
2894 | 2913 |
2895 #endif // DEBUG | 2914 #endif // DEBUG |
2896 | 2915 |
2897 } } // namespace v8::internal | 2916 } } // namespace v8::internal |
OLD | NEW |