| 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 |
| 500 if (executable == EXECUTABLE) { | 501 if (executable == EXECUTABLE) { |
| 501 chunk_size = RoundUp(CodePageAreaStartOffset() + body_size, | 502 chunk_size = RoundUp(CodePageAreaStartOffset() + body_size, |
| 502 OS::CommitPageSize()) + CodePageGuardSize(); | 503 OS::CommitPageSize()) + CodePageGuardSize(); |
| 503 | 504 |
| 504 // Check executable memory limit. | 505 // Check executable memory limit. |
| 505 if (size_executable_ + chunk_size > capacity_executable_) { | 506 if (size_executable_ + chunk_size > capacity_executable_) { |
| 506 LOG(isolate_, | 507 LOG(isolate_, |
| 507 StringEvent("MemoryAllocator::AllocateRawMemory", | 508 StringEvent("MemoryAllocator::AllocateRawMemory", |
| 508 "V8 Executable Allocation capacity exceeded")); | 509 "V8 Executable Allocation capacity exceeded")); |
| 509 return NULL; | 510 return NULL; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 522 } else { | 523 } else { |
| 523 base = AllocateAlignedMemory(chunk_size, | 524 base = AllocateAlignedMemory(chunk_size, |
| 524 MemoryChunk::kAlignment, | 525 MemoryChunk::kAlignment, |
| 525 executable, | 526 executable, |
| 526 &reservation); | 527 &reservation); |
| 527 if (base == NULL) return NULL; | 528 if (base == NULL) return NULL; |
| 528 // Update executable memory size. | 529 // Update executable memory size. |
| 529 size_executable_ += reservation.size(); | 530 size_executable_ += reservation.size(); |
| 530 } | 531 } |
| 531 | 532 |
| 532 #ifdef DEBUG | 533 if (Heap::ShouldZapGarbage()) { |
| 533 ZapBlock(base, CodePageGuardStartOffset()); | 534 ZapBlock(base, CodePageGuardStartOffset()); |
| 534 ZapBlock(base + CodePageAreaStartOffset(), body_size); | 535 ZapBlock(base + CodePageAreaStartOffset(), body_size); |
| 535 #endif | 536 } |
| 537 |
| 536 area_start = base + CodePageAreaStartOffset(); | 538 area_start = base + CodePageAreaStartOffset(); |
| 537 area_end = area_start + body_size; | 539 area_end = area_start + body_size; |
| 538 } else { | 540 } else { |
| 539 chunk_size = MemoryChunk::kObjectStartOffset + body_size; | 541 chunk_size = MemoryChunk::kObjectStartOffset + body_size; |
| 540 base = AllocateAlignedMemory(chunk_size, | 542 base = AllocateAlignedMemory(chunk_size, |
| 541 MemoryChunk::kAlignment, | 543 MemoryChunk::kAlignment, |
| 542 executable, | 544 executable, |
| 543 &reservation); | 545 &reservation); |
| 544 | 546 |
| 545 if (base == NULL) return NULL; | 547 if (base == NULL) return NULL; |
| 546 | 548 |
| 547 #ifdef DEBUG | 549 if (Heap::ShouldZapGarbage()) { |
| 548 ZapBlock(base, chunk_size); | 550 ZapBlock(base, chunk_size); |
| 549 #endif | 551 } |
| 550 | 552 |
| 551 area_start = base + Page::kObjectStartOffset; | 553 area_start = base + Page::kObjectStartOffset; |
| 552 area_end = base + chunk_size; | 554 area_end = base + chunk_size; |
| 553 } | 555 } |
| 554 | 556 |
| 555 isolate_->counters()->memory_allocated()-> | 557 isolate_->counters()->memory_allocated()-> |
| 556 Increment(static_cast<int>(chunk_size)); | 558 Increment(static_cast<int>(chunk_size)); |
| 557 | 559 |
| 558 LOG(isolate_, NewEvent("MemoryChunk", base, chunk_size)); | 560 LOG(isolate_, NewEvent("MemoryChunk", base, chunk_size)); |
| 559 if (owner != NULL) { | 561 if (owner != NULL) { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 615 chunk->size(), | 617 chunk->size(), |
| 616 chunk->executable()); | 618 chunk->executable()); |
| 617 } | 619 } |
| 618 } | 620 } |
| 619 | 621 |
| 620 | 622 |
| 621 bool MemoryAllocator::CommitBlock(Address start, | 623 bool MemoryAllocator::CommitBlock(Address start, |
| 622 size_t size, | 624 size_t size, |
| 623 Executability executable) { | 625 Executability executable) { |
| 624 if (!VirtualMemory::CommitRegion(start, size, executable)) return false; | 626 if (!VirtualMemory::CommitRegion(start, size, executable)) return false; |
| 625 #ifdef DEBUG | 627 |
| 626 ZapBlock(start, size); | 628 if (Heap::ShouldZapGarbage()) { |
| 627 #endif | 629 ZapBlock(start, size); |
| 630 } |
| 631 |
| 628 isolate_->counters()->memory_allocated()->Increment(static_cast<int>(size)); | 632 isolate_->counters()->memory_allocated()->Increment(static_cast<int>(size)); |
| 629 return true; | 633 return true; |
| 630 } | 634 } |
| 631 | 635 |
| 632 | 636 |
| 633 bool MemoryAllocator::UncommitBlock(Address start, size_t size) { | 637 bool MemoryAllocator::UncommitBlock(Address start, size_t size) { |
| 634 if (!VirtualMemory::UncommitRegion(start, size)) return false; | 638 if (!VirtualMemory::UncommitRegion(start, size)) return false; |
| 635 isolate_->counters()->memory_allocated()->Decrement(static_cast<int>(size)); | 639 isolate_->counters()->memory_allocated()->Decrement(static_cast<int>(size)); |
| 636 return true; | 640 return true; |
| 637 } | 641 } |
| (...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 978 } | 982 } |
| 979 } | 983 } |
| 980 heap()->FreeQueuedChunks(); | 984 heap()->FreeQueuedChunks(); |
| 981 } | 985 } |
| 982 | 986 |
| 983 | 987 |
| 984 #ifdef DEBUG | 988 #ifdef DEBUG |
| 985 void PagedSpace::Print() { } | 989 void PagedSpace::Print() { } |
| 986 #endif | 990 #endif |
| 987 | 991 |
| 988 | 992 #ifdef VERIFY_HEAP |
| 989 #ifdef DEBUG | |
| 990 void PagedSpace::Verify(ObjectVisitor* visitor) { | 993 void PagedSpace::Verify(ObjectVisitor* visitor) { |
| 991 // We can only iterate over the pages if they were swept precisely. | 994 // We can only iterate over the pages if they were swept precisely. |
| 992 if (was_swept_conservatively_) return; | 995 if (was_swept_conservatively_) return; |
| 993 | 996 |
| 994 bool allocation_pointer_found_in_space = | 997 bool allocation_pointer_found_in_space = |
| 995 (allocation_info_.top == allocation_info_.limit); | 998 (allocation_info_.top == allocation_info_.limit); |
| 996 PageIterator page_iterator(this); | 999 PageIterator page_iterator(this); |
| 997 while (page_iterator.has_next()) { | 1000 while (page_iterator.has_next()) { |
| 998 Page* page = page_iterator.next(); | 1001 Page* page = page_iterator.next(); |
| 999 ASSERT(page->owner() == this); | 1002 CHECK(page->owner() == this); |
| 1000 if (page == Page::FromAllocationTop(allocation_info_.top)) { | 1003 if (page == Page::FromAllocationTop(allocation_info_.top)) { |
| 1001 allocation_pointer_found_in_space = true; | 1004 allocation_pointer_found_in_space = true; |
| 1002 } | 1005 } |
| 1003 ASSERT(page->WasSweptPrecisely()); | 1006 CHECK(page->WasSweptPrecisely()); |
| 1004 HeapObjectIterator it(page, NULL); | 1007 HeapObjectIterator it(page, NULL); |
| 1005 Address end_of_previous_object = page->area_start(); | 1008 Address end_of_previous_object = page->area_start(); |
| 1006 Address top = page->area_end(); | 1009 Address top = page->area_end(); |
| 1007 int black_size = 0; | 1010 int black_size = 0; |
| 1008 for (HeapObject* object = it.Next(); object != NULL; object = it.Next()) { | 1011 for (HeapObject* object = it.Next(); object != NULL; object = it.Next()) { |
| 1009 ASSERT(end_of_previous_object <= object->address()); | 1012 CHECK(end_of_previous_object <= object->address()); |
| 1010 | 1013 |
| 1011 // The first word should be a map, and we expect all map pointers to | 1014 // The first word should be a map, and we expect all map pointers to |
| 1012 // be in map space. | 1015 // be in map space. |
| 1013 Map* map = object->map(); | 1016 Map* map = object->map(); |
| 1014 ASSERT(map->IsMap()); | 1017 CHECK(map->IsMap()); |
| 1015 ASSERT(heap()->map_space()->Contains(map)); | 1018 CHECK(heap()->map_space()->Contains(map)); |
| 1016 | 1019 |
| 1017 // Perform space-specific object verification. | 1020 // Perform space-specific object verification. |
| 1018 VerifyObject(object); | 1021 VerifyObject(object); |
| 1019 | 1022 |
| 1020 // The object itself should look OK. | 1023 // The object itself should look OK. |
| 1021 object->Verify(); | 1024 object->Verify(); |
| 1022 | 1025 |
| 1023 // All the interior pointers should be contained in the heap. | 1026 // All the interior pointers should be contained in the heap. |
| 1024 int size = object->Size(); | 1027 int size = object->Size(); |
| 1025 object->IterateBody(map->instance_type(), size, visitor); | 1028 object->IterateBody(map->instance_type(), size, visitor); |
| 1026 if (Marking::IsBlack(Marking::MarkBitFrom(object))) { | 1029 if (Marking::IsBlack(Marking::MarkBitFrom(object))) { |
| 1027 black_size += size; | 1030 black_size += size; |
| 1028 } | 1031 } |
| 1029 | 1032 |
| 1030 ASSERT(object->address() + size <= top); | 1033 CHECK(object->address() + size <= top); |
| 1031 end_of_previous_object = object->address() + size; | 1034 end_of_previous_object = object->address() + size; |
| 1032 } | 1035 } |
| 1033 ASSERT_LE(black_size, page->LiveBytes()); | 1036 CHECK_LE(black_size, page->LiveBytes()); |
| 1034 } | 1037 } |
| 1035 ASSERT(allocation_pointer_found_in_space); | 1038 CHECK(allocation_pointer_found_in_space); |
| 1036 } | 1039 } |
| 1037 #endif | 1040 #endif // VERIFY_HEAP |
| 1038 | |
| 1039 | 1041 |
| 1040 // ----------------------------------------------------------------------------- | 1042 // ----------------------------------------------------------------------------- |
| 1041 // NewSpace implementation | 1043 // NewSpace implementation |
| 1042 | 1044 |
| 1043 | 1045 |
| 1044 bool NewSpace::SetUp(int reserved_semispace_capacity, | 1046 bool NewSpace::SetUp(int reserved_semispace_capacity, |
| 1045 int maximum_semispace_capacity) { | 1047 int maximum_semispace_capacity) { |
| 1046 // Set up new space based on the preallocated memory block defined by | 1048 // 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. | 1049 // 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 | 1050 // 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( | 1254 heap()->incremental_marking()->Step( |
| 1253 bytes_allocated, IncrementalMarking::GC_VIA_STACK_GUARD); | 1255 bytes_allocated, IncrementalMarking::GC_VIA_STACK_GUARD); |
| 1254 top_on_previous_step_ = to_space_.page_low(); | 1256 top_on_previous_step_ = to_space_.page_low(); |
| 1255 return AllocateRaw(size_in_bytes); | 1257 return AllocateRaw(size_in_bytes); |
| 1256 } else { | 1258 } else { |
| 1257 return Failure::RetryAfterGC(); | 1259 return Failure::RetryAfterGC(); |
| 1258 } | 1260 } |
| 1259 } | 1261 } |
| 1260 | 1262 |
| 1261 | 1263 |
| 1262 #ifdef DEBUG | 1264 #ifdef VERIFY_HEAP |
| 1263 // We do not use the SemiSpaceIterator because verification doesn't assume | 1265 // We do not use the SemiSpaceIterator because verification doesn't assume |
| 1264 // that it works (it depends on the invariants we are checking). | 1266 // that it works (it depends on the invariants we are checking). |
| 1265 void NewSpace::Verify() { | 1267 void NewSpace::Verify() { |
| 1266 // The allocation pointer should be in the space or at the very end. | 1268 // The allocation pointer should be in the space or at the very end. |
| 1267 ASSERT_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); | 1269 ASSERT_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); |
| 1268 | 1270 |
| 1269 // There should be objects packed in from the low address up to the | 1271 // There should be objects packed in from the low address up to the |
| 1270 // allocation pointer. | 1272 // allocation pointer. |
| 1271 Address current = to_space_.first_page()->area_start(); | 1273 Address current = to_space_.first_page()->area_start(); |
| 1272 CHECK_EQ(current, to_space_.space_start()); | 1274 CHECK_EQ(current, to_space_.space_start()); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1301 } else { | 1303 } else { |
| 1302 // At end of page, switch to next page. | 1304 // At end of page, switch to next page. |
| 1303 NewSpacePage* page = NewSpacePage::FromLimit(current)->next_page(); | 1305 NewSpacePage* page = NewSpacePage::FromLimit(current)->next_page(); |
| 1304 // Next page should be valid. | 1306 // Next page should be valid. |
| 1305 CHECK(!page->is_anchor()); | 1307 CHECK(!page->is_anchor()); |
| 1306 current = page->area_start(); | 1308 current = page->area_start(); |
| 1307 } | 1309 } |
| 1308 } | 1310 } |
| 1309 | 1311 |
| 1310 // Check semi-spaces. | 1312 // Check semi-spaces. |
| 1311 ASSERT_EQ(from_space_.id(), kFromSpace); | 1313 CHECK_EQ(from_space_.id(), kFromSpace); |
| 1312 ASSERT_EQ(to_space_.id(), kToSpace); | 1314 CHECK_EQ(to_space_.id(), kToSpace); |
| 1313 from_space_.Verify(); | 1315 from_space_.Verify(); |
| 1314 to_space_.Verify(); | 1316 to_space_.Verify(); |
| 1315 } | 1317 } |
| 1316 #endif | 1318 #endif |
| 1317 | 1319 |
| 1318 // ----------------------------------------------------------------------------- | 1320 // ----------------------------------------------------------------------------- |
| 1319 // SemiSpace implementation | 1321 // SemiSpace implementation |
| 1320 | 1322 |
| 1321 void SemiSpace::SetUp(Address start, | 1323 void SemiSpace::SetUp(Address start, |
| 1322 int initial_capacity, | 1324 int initial_capacity, |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1518 // Mark all pages up to the one containing mark. | 1520 // Mark all pages up to the one containing mark. |
| 1519 NewSpacePageIterator it(space_start(), mark); | 1521 NewSpacePageIterator it(space_start(), mark); |
| 1520 while (it.has_next()) { | 1522 while (it.has_next()) { |
| 1521 it.next()->SetFlag(MemoryChunk::NEW_SPACE_BELOW_AGE_MARK); | 1523 it.next()->SetFlag(MemoryChunk::NEW_SPACE_BELOW_AGE_MARK); |
| 1522 } | 1524 } |
| 1523 } | 1525 } |
| 1524 | 1526 |
| 1525 | 1527 |
| 1526 #ifdef DEBUG | 1528 #ifdef DEBUG |
| 1527 void SemiSpace::Print() { } | 1529 void SemiSpace::Print() { } |
| 1530 #endif |
| 1528 | 1531 |
| 1529 | 1532 #ifdef VERIFY_HEAP |
| 1530 void SemiSpace::Verify() { | 1533 void SemiSpace::Verify() { |
| 1531 bool is_from_space = (id_ == kFromSpace); | 1534 bool is_from_space = (id_ == kFromSpace); |
| 1532 NewSpacePage* page = anchor_.next_page(); | 1535 NewSpacePage* page = anchor_.next_page(); |
| 1533 CHECK(anchor_.semi_space() == this); | 1536 CHECK(anchor_.semi_space() == this); |
| 1534 while (page != &anchor_) { | 1537 while (page != &anchor_) { |
| 1535 CHECK(page->semi_space() == this); | 1538 CHECK(page->semi_space() == this); |
| 1536 CHECK(page->InNewSpace()); | 1539 CHECK(page->InNewSpace()); |
| 1537 CHECK(page->IsFlagSet(is_from_space ? MemoryChunk::IN_FROM_SPACE | 1540 CHECK(page->IsFlagSet(is_from_space ? MemoryChunk::IN_FROM_SPACE |
| 1538 : MemoryChunk::IN_TO_SPACE)); | 1541 : MemoryChunk::IN_TO_SPACE)); |
| 1539 CHECK(!page->IsFlagSet(is_from_space ? MemoryChunk::IN_TO_SPACE | 1542 CHECK(!page->IsFlagSet(is_from_space ? MemoryChunk::IN_TO_SPACE |
| 1540 : MemoryChunk::IN_FROM_SPACE)); | 1543 : MemoryChunk::IN_FROM_SPACE)); |
| 1541 CHECK(page->IsFlagSet(MemoryChunk::POINTERS_TO_HERE_ARE_INTERESTING)); | 1544 CHECK(page->IsFlagSet(MemoryChunk::POINTERS_TO_HERE_ARE_INTERESTING)); |
| 1542 if (!is_from_space) { | 1545 if (!is_from_space) { |
| 1543 // The pointers-from-here-are-interesting flag isn't updated dynamically | 1546 // The pointers-from-here-are-interesting flag isn't updated dynamically |
| 1544 // on from-space pages, so it might be out of sync with the marking state. | 1547 // on from-space pages, so it might be out of sync with the marking state. |
| 1545 if (page->heap()->incremental_marking()->IsMarking()) { | 1548 if (page->heap()->incremental_marking()->IsMarking()) { |
| 1546 CHECK(page->IsFlagSet(MemoryChunk::POINTERS_FROM_HERE_ARE_INTERESTING)); | 1549 CHECK(page->IsFlagSet(MemoryChunk::POINTERS_FROM_HERE_ARE_INTERESTING)); |
| 1547 } else { | 1550 } else { |
| 1548 CHECK(!page->IsFlagSet( | 1551 CHECK(!page->IsFlagSet( |
| 1549 MemoryChunk::POINTERS_FROM_HERE_ARE_INTERESTING)); | 1552 MemoryChunk::POINTERS_FROM_HERE_ARE_INTERESTING)); |
| 1550 } | 1553 } |
| 1551 // TODO(gc): Check that the live_bytes_count_ field matches the | 1554 // 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). | 1555 // black marking on the page (if we make it match in new-space). |
| 1553 } | 1556 } |
| 1554 CHECK(page->IsFlagSet(MemoryChunk::SCAN_ON_SCAVENGE)); | 1557 CHECK(page->IsFlagSet(MemoryChunk::SCAN_ON_SCAVENGE)); |
| 1555 CHECK(page->prev_page()->next_page() == page); | 1558 CHECK(page->prev_page()->next_page() == page); |
| 1556 page = page->next_page(); | 1559 page = page->next_page(); |
| 1557 } | 1560 } |
| 1558 } | 1561 } |
| 1562 #endif |
| 1559 | 1563 |
| 1560 | 1564 #ifdef DEBUG |
| 1561 void SemiSpace::AssertValidRange(Address start, Address end) { | 1565 void SemiSpace::AssertValidRange(Address start, Address end) { |
| 1562 // Addresses belong to same semi-space | 1566 // Addresses belong to same semi-space |
| 1563 NewSpacePage* page = NewSpacePage::FromLimit(start); | 1567 NewSpacePage* page = NewSpacePage::FromLimit(start); |
| 1564 NewSpacePage* end_page = NewSpacePage::FromLimit(end); | 1568 NewSpacePage* end_page = NewSpacePage::FromLimit(end); |
| 1565 SemiSpace* space = page->semi_space(); | 1569 SemiSpace* space = page->semi_space(); |
| 1566 CHECK_EQ(space, end_page->semi_space()); | 1570 CHECK_EQ(space, end_page->semi_space()); |
| 1567 // Start address is before end address, either on same page, | 1571 // Start address is before end address, either on same page, |
| 1568 // or end address is on a later page in the linked list of | 1572 // or end address is on a later page in the linked list of |
| 1569 // semi-space pages. | 1573 // semi-space pages. |
| 1570 if (page == end_page) { | 1574 if (page == end_page) { |
| (...skipping 973 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2544 // collection. | 2548 // collection. |
| 2545 accounting_stats_.AllocateBytes(free_list_.available()); | 2549 accounting_stats_.AllocateBytes(free_list_.available()); |
| 2546 | 2550 |
| 2547 // Clear the free list before a full GC---it will be rebuilt afterward. | 2551 // Clear the free list before a full GC---it will be rebuilt afterward. |
| 2548 free_list_.Reset(); | 2552 free_list_.Reset(); |
| 2549 } | 2553 } |
| 2550 | 2554 |
| 2551 | 2555 |
| 2552 // ----------------------------------------------------------------------------- | 2556 // ----------------------------------------------------------------------------- |
| 2553 // MapSpace implementation | 2557 // MapSpace implementation |
| 2558 // TODO(mvstanton): this is weird...the compiler can't make a vtable unless |
| 2559 // there is at least one non-inlined virtual function. I would prefer to hide |
| 2560 // the VerifyObject definition behind VERIFY_HEAP. |
| 2554 | 2561 |
| 2555 #ifdef DEBUG | |
| 2556 void MapSpace::VerifyObject(HeapObject* object) { | 2562 void MapSpace::VerifyObject(HeapObject* object) { |
| 2557 // The object should be a map or a free-list node. | 2563 // The object should be a map or a free-list node. |
| 2558 ASSERT(object->IsMap() || object->IsFreeSpace()); | 2564 CHECK(object->IsMap() || object->IsFreeSpace()); |
| 2559 } | 2565 } |
| 2560 #endif | |
| 2561 | 2566 |
| 2562 | 2567 |
| 2563 // ----------------------------------------------------------------------------- | 2568 // ----------------------------------------------------------------------------- |
| 2564 // GlobalPropertyCellSpace implementation | 2569 // GlobalPropertyCellSpace implementation |
| 2570 // TODO(mvstanton): this is weird...the compiler can't make a vtable unless |
| 2571 // there is at least one non-inlined virtual function. I would prefer to hide |
| 2572 // the VerifyObject definition behind VERIFY_HEAP. |
| 2565 | 2573 |
| 2566 #ifdef DEBUG | |
| 2567 void CellSpace::VerifyObject(HeapObject* object) { | 2574 void CellSpace::VerifyObject(HeapObject* object) { |
| 2568 // The object should be a global object property cell or a free-list node. | 2575 // The object should be a global object property cell or a free-list node. |
| 2569 ASSERT(object->IsJSGlobalPropertyCell() || | 2576 CHECK(object->IsJSGlobalPropertyCell() || |
| 2570 object->map() == heap()->two_pointer_filler_map()); | 2577 object->map() == heap()->two_pointer_filler_map()); |
| 2571 } | 2578 } |
| 2572 #endif | |
| 2573 | 2579 |
| 2574 | 2580 |
| 2575 // ----------------------------------------------------------------------------- | 2581 // ----------------------------------------------------------------------------- |
| 2576 // LargeObjectIterator | 2582 // LargeObjectIterator |
| 2577 | 2583 |
| 2578 LargeObjectIterator::LargeObjectIterator(LargeObjectSpace* space) { | 2584 LargeObjectIterator::LargeObjectIterator(LargeObjectSpace* space) { |
| 2579 current_ = space->first_page_; | 2585 current_ = space->first_page_; |
| 2580 size_func_ = NULL; | 2586 size_func_ = NULL; |
| 2581 } | 2587 } |
| 2582 | 2588 |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2672 for (uintptr_t key = base; key <= limit; key++) { | 2678 for (uintptr_t key = base; key <= limit; key++) { |
| 2673 HashMap::Entry* entry = chunk_map_.Lookup(reinterpret_cast<void*>(key), | 2679 HashMap::Entry* entry = chunk_map_.Lookup(reinterpret_cast<void*>(key), |
| 2674 static_cast<uint32_t>(key), | 2680 static_cast<uint32_t>(key), |
| 2675 true); | 2681 true); |
| 2676 ASSERT(entry != NULL); | 2682 ASSERT(entry != NULL); |
| 2677 entry->value = page; | 2683 entry->value = page; |
| 2678 } | 2684 } |
| 2679 | 2685 |
| 2680 HeapObject* object = page->GetObject(); | 2686 HeapObject* object = page->GetObject(); |
| 2681 | 2687 |
| 2682 #ifdef DEBUG | 2688 if (Heap::ShouldZapGarbage()) { |
| 2683 // Make the object consistent so the heap can be vefified in OldSpaceStep. | 2689 // Make the object consistent so the heap can be verified in OldSpaceStep. |
| 2684 reinterpret_cast<Object**>(object->address())[0] = | 2690 // We only need to do this in debug builds or if verify_heap is on. |
| 2685 heap()->fixed_array_map(); | 2691 reinterpret_cast<Object**>(object->address())[0] = |
| 2686 reinterpret_cast<Object**>(object->address())[1] = Smi::FromInt(0); | 2692 heap()->fixed_array_map(); |
| 2687 #endif | 2693 reinterpret_cast<Object**>(object->address())[1] = Smi::FromInt(0); |
| 2694 } |
| 2688 | 2695 |
| 2689 heap()->incremental_marking()->OldSpaceStep(object_size); | 2696 heap()->incremental_marking()->OldSpaceStep(object_size); |
| 2690 return object; | 2697 return object; |
| 2691 } | 2698 } |
| 2692 | 2699 |
| 2693 | 2700 |
| 2694 // GC support | 2701 // GC support |
| 2695 MaybeObject* LargeObjectSpace::FindObject(Address a) { | 2702 MaybeObject* LargeObjectSpace::FindObject(Address a) { |
| 2696 LargePage* page = FindPage(a); | 2703 LargePage* page = FindPage(a); |
| 2697 if (page != NULL) { | 2704 if (page != NULL) { |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2776 MemoryChunk* chunk = MemoryChunk::FromAddress(address); | 2783 MemoryChunk* chunk = MemoryChunk::FromAddress(address); |
| 2777 | 2784 |
| 2778 bool owned = (chunk->owner() == this); | 2785 bool owned = (chunk->owner() == this); |
| 2779 | 2786 |
| 2780 SLOW_ASSERT(!owned || !FindObject(address)->IsFailure()); | 2787 SLOW_ASSERT(!owned || !FindObject(address)->IsFailure()); |
| 2781 | 2788 |
| 2782 return owned; | 2789 return owned; |
| 2783 } | 2790 } |
| 2784 | 2791 |
| 2785 | 2792 |
| 2786 #ifdef DEBUG | 2793 #ifdef VERIFY_HEAP |
| 2787 // We do not assume that the large object iterator works, because it depends | 2794 // We do not assume that the large object iterator works, because it depends |
| 2788 // on the invariants we are checking during verification. | 2795 // on the invariants we are checking during verification. |
| 2789 void LargeObjectSpace::Verify() { | 2796 void LargeObjectSpace::Verify() { |
| 2790 for (LargePage* chunk = first_page_; | 2797 for (LargePage* chunk = first_page_; |
| 2791 chunk != NULL; | 2798 chunk != NULL; |
| 2792 chunk = chunk->next_page()) { | 2799 chunk = chunk->next_page()) { |
| 2793 // Each chunk contains an object that starts at the large object page's | 2800 // Each chunk contains an object that starts at the large object page's |
| 2794 // object area start. | 2801 // object area start. |
| 2795 HeapObject* object = chunk->GetObject(); | 2802 HeapObject* object = chunk->GetObject(); |
| 2796 Page* page = Page::FromAddress(object->address()); | 2803 Page* page = Page::FromAddress(object->address()); |
| 2797 ASSERT(object->address() == page->area_start()); | 2804 CHECK(object->address() == page->area_start()); |
| 2798 | 2805 |
| 2799 // The first word should be a map, and we expect all map pointers to be | 2806 // The first word should be a map, and we expect all map pointers to be |
| 2800 // in map space. | 2807 // in map space. |
| 2801 Map* map = object->map(); | 2808 Map* map = object->map(); |
| 2802 ASSERT(map->IsMap()); | 2809 CHECK(map->IsMap()); |
| 2803 ASSERT(heap()->map_space()->Contains(map)); | 2810 CHECK(heap()->map_space()->Contains(map)); |
| 2804 | 2811 |
| 2805 // We have only code, sequential strings, external strings | 2812 // We have only code, sequential strings, external strings |
| 2806 // (sequential strings that have been morphed into external | 2813 // (sequential strings that have been morphed into external |
| 2807 // strings), fixed arrays, and byte arrays in large object space. | 2814 // strings), fixed arrays, and byte arrays in large object space. |
| 2808 ASSERT(object->IsCode() || object->IsSeqString() || | 2815 CHECK(object->IsCode() || object->IsSeqString() || |
| 2809 object->IsExternalString() || object->IsFixedArray() || | 2816 object->IsExternalString() || object->IsFixedArray() || |
| 2810 object->IsFixedDoubleArray() || object->IsByteArray()); | 2817 object->IsFixedDoubleArray() || object->IsByteArray()); |
| 2811 | 2818 |
| 2812 // The object itself should look OK. | 2819 // The object itself should look OK. |
| 2813 object->Verify(); | 2820 object->Verify(); |
| 2814 | 2821 |
| 2815 // Byte arrays and strings don't have interior pointers. | 2822 // Byte arrays and strings don't have interior pointers. |
| 2816 if (object->IsCode()) { | 2823 if (object->IsCode()) { |
| 2817 VerifyPointersVisitor code_visitor; | 2824 VerifyPointersVisitor code_visitor; |
| 2818 object->IterateBody(map->instance_type(), | 2825 object->IterateBody(map->instance_type(), |
| 2819 object->Size(), | 2826 object->Size(), |
| 2820 &code_visitor); | 2827 &code_visitor); |
| 2821 } else if (object->IsFixedArray()) { | 2828 } else if (object->IsFixedArray()) { |
| 2822 FixedArray* array = FixedArray::cast(object); | 2829 FixedArray* array = FixedArray::cast(object); |
| 2823 for (int j = 0; j < array->length(); j++) { | 2830 for (int j = 0; j < array->length(); j++) { |
| 2824 Object* element = array->get(j); | 2831 Object* element = array->get(j); |
| 2825 if (element->IsHeapObject()) { | 2832 if (element->IsHeapObject()) { |
| 2826 HeapObject* element_object = HeapObject::cast(element); | 2833 HeapObject* element_object = HeapObject::cast(element); |
| 2827 ASSERT(heap()->Contains(element_object)); | 2834 CHECK(heap()->Contains(element_object)); |
| 2828 ASSERT(element_object->map()->IsMap()); | 2835 CHECK(element_object->map()->IsMap()); |
| 2829 } | 2836 } |
| 2830 } | 2837 } |
| 2831 } | 2838 } |
| 2832 } | 2839 } |
| 2833 } | 2840 } |
| 2841 #endif |
| 2834 | 2842 |
| 2835 | 2843 |
| 2844 #ifdef DEBUG |
| 2836 void LargeObjectSpace::Print() { | 2845 void LargeObjectSpace::Print() { |
| 2837 LargeObjectIterator it(this); | 2846 LargeObjectIterator it(this); |
| 2838 for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) { | 2847 for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) { |
| 2839 obj->Print(); | 2848 obj->Print(); |
| 2840 } | 2849 } |
| 2841 } | 2850 } |
| 2842 | 2851 |
| 2843 | 2852 |
| 2844 void LargeObjectSpace::ReportStatistics() { | 2853 void LargeObjectSpace::ReportStatistics() { |
| 2845 PrintF(" size: %" V8_PTR_PREFIX "d\n", size_); | 2854 PrintF(" size: %" V8_PTR_PREFIX "d\n", size_); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2888 object->ShortPrint(); | 2897 object->ShortPrint(); |
| 2889 PrintF("\n"); | 2898 PrintF("\n"); |
| 2890 } | 2899 } |
| 2891 printf(" --------------------------------------\n"); | 2900 printf(" --------------------------------------\n"); |
| 2892 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); | 2901 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); |
| 2893 } | 2902 } |
| 2894 | 2903 |
| 2895 #endif // DEBUG | 2904 #endif // DEBUG |
| 2896 | 2905 |
| 2897 } } // namespace v8::internal | 2906 } } // namespace v8::internal |
| OLD | NEW |