| 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 11 matching lines...) Expand all Loading... |
| 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #include "v8.h" | 28 #include "v8.h" |
| 29 | 29 |
| 30 #include "macro-assembler.h" | 30 #include "macro-assembler.h" |
| 31 #include "mark-compact.h" | 31 #include "mark-compact.h" |
| 32 #include "msan.h" |
| 32 #include "platform.h" | 33 #include "platform.h" |
| 33 | 34 |
| 34 namespace v8 { | 35 namespace v8 { |
| 35 namespace internal { | 36 namespace internal { |
| 36 | 37 |
| 37 | 38 |
| 38 // ---------------------------------------------------------------------------- | 39 // ---------------------------------------------------------------------------- |
| 39 // HeapObjectIterator | 40 // HeapObjectIterator |
| 40 | 41 |
| 41 HeapObjectIterator::HeapObjectIterator(PagedSpace* space) { | 42 HeapObjectIterator::HeapObjectIterator(PagedSpace* space) { |
| (...skipping 668 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 710 } | 711 } |
| 711 | 712 |
| 712 MemoryChunk* result = MemoryChunk::Initialize(heap, | 713 MemoryChunk* result = MemoryChunk::Initialize(heap, |
| 713 base, | 714 base, |
| 714 chunk_size, | 715 chunk_size, |
| 715 area_start, | 716 area_start, |
| 716 area_end, | 717 area_end, |
| 717 executable, | 718 executable, |
| 718 owner); | 719 owner); |
| 719 result->set_reserved_memory(&reservation); | 720 result->set_reserved_memory(&reservation); |
| 721 MSAN_MEMORY_IS_INITIALIZED(base, chunk_size); |
| 720 return result; | 722 return result; |
| 721 } | 723 } |
| 722 | 724 |
| 723 | 725 |
| 724 void Page::ResetFreeListStatistics() { | 726 void Page::ResetFreeListStatistics() { |
| 725 non_available_small_blocks_ = 0; | 727 non_available_small_blocks_ = 0; |
| 726 available_in_small_free_list_ = 0; | 728 available_in_small_free_list_ = 0; |
| 727 available_in_medium_free_list_ = 0; | 729 available_in_medium_free_list_ = 0; |
| 728 available_in_large_free_list_ = 0; | 730 available_in_large_free_list_ = 0; |
| 729 available_in_huge_free_list_ = 0; | 731 available_in_huge_free_list_ = 0; |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 951 if (id == CODE_SPACE) { | 953 if (id == CODE_SPACE) { |
| 952 area_size_ = heap->isolate()->memory_allocator()-> | 954 area_size_ = heap->isolate()->memory_allocator()-> |
| 953 CodePageAreaSize(); | 955 CodePageAreaSize(); |
| 954 } else { | 956 } else { |
| 955 area_size_ = Page::kPageSize - Page::kObjectStartOffset; | 957 area_size_ = Page::kPageSize - Page::kObjectStartOffset; |
| 956 } | 958 } |
| 957 max_capacity_ = (RoundDown(max_capacity, Page::kPageSize) / Page::kPageSize) | 959 max_capacity_ = (RoundDown(max_capacity, Page::kPageSize) / Page::kPageSize) |
| 958 * AreaSize(); | 960 * AreaSize(); |
| 959 accounting_stats_.Clear(); | 961 accounting_stats_.Clear(); |
| 960 | 962 |
| 961 allocation_info_.top = NULL; | 963 allocation_info_.set_top(NULL); |
| 962 allocation_info_.limit = NULL; | 964 allocation_info_.set_limit(NULL); |
| 963 | 965 |
| 964 anchor_.InitializeAsAnchor(this); | 966 anchor_.InitializeAsAnchor(this); |
| 965 } | 967 } |
| 966 | 968 |
| 967 | 969 |
| 968 bool PagedSpace::SetUp() { | 970 bool PagedSpace::SetUp() { |
| 969 return true; | 971 return true; |
| 970 } | 972 } |
| 971 | 973 |
| 972 | 974 |
| 973 bool PagedSpace::HasBeenSetUp() { | 975 bool PagedSpace::HasBeenSetUp() { |
| 974 return true; | 976 return true; |
| 975 } | 977 } |
| 976 | 978 |
| 977 | 979 |
| 978 void PagedSpace::TearDown() { | 980 void PagedSpace::TearDown() { |
| 979 PageIterator iterator(this); | 981 PageIterator iterator(this); |
| 980 while (iterator.has_next()) { | 982 while (iterator.has_next()) { |
| 981 heap()->isolate()->memory_allocator()->Free(iterator.next()); | 983 heap()->isolate()->memory_allocator()->Free(iterator.next()); |
| 982 } | 984 } |
| 983 anchor_.set_next_page(&anchor_); | 985 anchor_.set_next_page(&anchor_); |
| 984 anchor_.set_prev_page(&anchor_); | 986 anchor_.set_prev_page(&anchor_); |
| 985 accounting_stats_.Clear(); | 987 accounting_stats_.Clear(); |
| 986 } | 988 } |
| 987 | 989 |
| 988 | 990 |
| 989 size_t PagedSpace::CommittedPhysicalMemory() { | 991 size_t PagedSpace::CommittedPhysicalMemory() { |
| 990 if (!VirtualMemory::HasLazyCommits()) return CommittedMemory(); | 992 if (!VirtualMemory::HasLazyCommits()) return CommittedMemory(); |
| 991 MemoryChunk::UpdateHighWaterMark(allocation_info_.top); | 993 MemoryChunk::UpdateHighWaterMark(allocation_info_.top()); |
| 992 size_t size = 0; | 994 size_t size = 0; |
| 993 PageIterator it(this); | 995 PageIterator it(this); |
| 994 while (it.has_next()) { | 996 while (it.has_next()) { |
| 995 size += it.next()->CommittedPhysicalMemory(); | 997 size += it.next()->CommittedPhysicalMemory(); |
| 996 } | 998 } |
| 997 return size; | 999 return size; |
| 998 } | 1000 } |
| 999 | 1001 |
| 1000 | 1002 |
| 1001 MaybeObject* PagedSpace::FindObject(Address addr) { | 1003 MaybeObject* PagedSpace::FindObject(Address addr) { |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1070 case PROPERTY_CELL_SPACE: | 1072 case PROPERTY_CELL_SPACE: |
| 1071 size = 8 * kPointerSize * KB; | 1073 size = 8 * kPointerSize * KB; |
| 1072 break; | 1074 break; |
| 1073 case CODE_SPACE: | 1075 case CODE_SPACE: |
| 1074 if (heap()->isolate()->code_range()->exists()) { | 1076 if (heap()->isolate()->code_range()->exists()) { |
| 1075 // When code range exists, code pages are allocated in a special way | 1077 // When code range exists, code pages are allocated in a special way |
| 1076 // (from the reserved code range). That part of the code is not yet | 1078 // (from the reserved code range). That part of the code is not yet |
| 1077 // upgraded to handle small pages. | 1079 // upgraded to handle small pages. |
| 1078 size = AreaSize(); | 1080 size = AreaSize(); |
| 1079 } else { | 1081 } else { |
| 1080 size = 384 * KB; | 1082 #if V8_TARGET_ARCH_MIPS |
| 1083 // TODO(plind): Investigate larger code stubs size on MIPS. |
| 1084 size = 480 * KB; |
| 1085 #else |
| 1086 size = 416 * KB; |
| 1087 #endif |
| 1081 } | 1088 } |
| 1082 break; | 1089 break; |
| 1083 default: | 1090 default: |
| 1084 UNREACHABLE(); | 1091 UNREACHABLE(); |
| 1085 } | 1092 } |
| 1086 return Min(size, AreaSize()); | 1093 return Min(size, AreaSize()); |
| 1087 } | 1094 } |
| 1088 | 1095 |
| 1089 | 1096 |
| 1090 int PagedSpace::CountTotalPages() { | 1097 int PagedSpace::CountTotalPages() { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1128 } | 1135 } |
| 1129 | 1136 |
| 1130 if (page->WasSwept()) { | 1137 if (page->WasSwept()) { |
| 1131 intptr_t size = free_list_.EvictFreeListItems(page); | 1138 intptr_t size = free_list_.EvictFreeListItems(page); |
| 1132 accounting_stats_.AllocateBytes(size); | 1139 accounting_stats_.AllocateBytes(size); |
| 1133 ASSERT_EQ(AreaSize(), static_cast<int>(size)); | 1140 ASSERT_EQ(AreaSize(), static_cast<int>(size)); |
| 1134 } else { | 1141 } else { |
| 1135 DecreaseUnsweptFreeBytes(page); | 1142 DecreaseUnsweptFreeBytes(page); |
| 1136 } | 1143 } |
| 1137 | 1144 |
| 1138 if (Page::FromAllocationTop(allocation_info_.top) == page) { | 1145 if (Page::FromAllocationTop(allocation_info_.top()) == page) { |
| 1139 allocation_info_.top = allocation_info_.limit = NULL; | 1146 allocation_info_.set_top(NULL); |
| 1147 allocation_info_.set_limit(NULL); |
| 1140 } | 1148 } |
| 1141 | 1149 |
| 1142 if (unlink) { | 1150 if (unlink) { |
| 1143 page->Unlink(); | 1151 page->Unlink(); |
| 1144 } | 1152 } |
| 1145 if (page->IsFlagSet(MemoryChunk::CONTAINS_ONLY_DATA)) { | 1153 if (page->IsFlagSet(MemoryChunk::CONTAINS_ONLY_DATA)) { |
| 1146 heap()->isolate()->memory_allocator()->Free(page); | 1154 heap()->isolate()->memory_allocator()->Free(page); |
| 1147 } else { | 1155 } else { |
| 1148 heap()->QueueMemoryChunkForFree(page); | 1156 heap()->QueueMemoryChunkForFree(page); |
| 1149 } | 1157 } |
| 1150 | 1158 |
| 1151 ASSERT(Capacity() > 0); | 1159 ASSERT(Capacity() > 0); |
| 1152 accounting_stats_.ShrinkSpace(AreaSize()); | 1160 accounting_stats_.ShrinkSpace(AreaSize()); |
| 1153 } | 1161 } |
| 1154 | 1162 |
| 1155 | 1163 |
| 1156 #ifdef DEBUG | 1164 #ifdef DEBUG |
| 1157 void PagedSpace::Print() { } | 1165 void PagedSpace::Print() { } |
| 1158 #endif | 1166 #endif |
| 1159 | 1167 |
| 1160 #ifdef VERIFY_HEAP | 1168 #ifdef VERIFY_HEAP |
| 1161 void PagedSpace::Verify(ObjectVisitor* visitor) { | 1169 void PagedSpace::Verify(ObjectVisitor* visitor) { |
| 1162 // We can only iterate over the pages if they were swept precisely. | 1170 // We can only iterate over the pages if they were swept precisely. |
| 1163 if (was_swept_conservatively_) return; | 1171 if (was_swept_conservatively_) return; |
| 1164 | 1172 |
| 1165 bool allocation_pointer_found_in_space = | 1173 bool allocation_pointer_found_in_space = |
| 1166 (allocation_info_.top == allocation_info_.limit); | 1174 (allocation_info_.top() == allocation_info_.limit()); |
| 1167 PageIterator page_iterator(this); | 1175 PageIterator page_iterator(this); |
| 1168 while (page_iterator.has_next()) { | 1176 while (page_iterator.has_next()) { |
| 1169 Page* page = page_iterator.next(); | 1177 Page* page = page_iterator.next(); |
| 1170 CHECK(page->owner() == this); | 1178 CHECK(page->owner() == this); |
| 1171 if (page == Page::FromAllocationTop(allocation_info_.top)) { | 1179 if (page == Page::FromAllocationTop(allocation_info_.top())) { |
| 1172 allocation_pointer_found_in_space = true; | 1180 allocation_pointer_found_in_space = true; |
| 1173 } | 1181 } |
| 1174 CHECK(page->WasSweptPrecisely()); | 1182 CHECK(page->WasSweptPrecisely()); |
| 1175 HeapObjectIterator it(page, NULL); | 1183 HeapObjectIterator it(page, NULL); |
| 1176 Address end_of_previous_object = page->area_start(); | 1184 Address end_of_previous_object = page->area_start(); |
| 1177 Address top = page->area_end(); | 1185 Address top = page->area_end(); |
| 1178 int black_size = 0; | 1186 int black_size = 0; |
| 1179 for (HeapObject* object = it.Next(); object != NULL; object = it.Next()) { | 1187 for (HeapObject* object = it.Next(); object != NULL; object = it.Next()) { |
| 1180 CHECK(end_of_previous_object <= object->address()); | 1188 CHECK(end_of_previous_object <= object->address()); |
| 1181 | 1189 |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1272 if (allocated_histogram_) { | 1280 if (allocated_histogram_) { |
| 1273 DeleteArray(allocated_histogram_); | 1281 DeleteArray(allocated_histogram_); |
| 1274 allocated_histogram_ = NULL; | 1282 allocated_histogram_ = NULL; |
| 1275 } | 1283 } |
| 1276 if (promoted_histogram_) { | 1284 if (promoted_histogram_) { |
| 1277 DeleteArray(promoted_histogram_); | 1285 DeleteArray(promoted_histogram_); |
| 1278 promoted_histogram_ = NULL; | 1286 promoted_histogram_ = NULL; |
| 1279 } | 1287 } |
| 1280 | 1288 |
| 1281 start_ = NULL; | 1289 start_ = NULL; |
| 1282 allocation_info_.top = NULL; | 1290 allocation_info_.set_top(NULL); |
| 1283 allocation_info_.limit = NULL; | 1291 allocation_info_.set_limit(NULL); |
| 1284 | 1292 |
| 1285 to_space_.TearDown(); | 1293 to_space_.TearDown(); |
| 1286 from_space_.TearDown(); | 1294 from_space_.TearDown(); |
| 1287 | 1295 |
| 1288 LOG(heap()->isolate(), DeleteEvent("InitialChunk", chunk_base_)); | 1296 LOG(heap()->isolate(), DeleteEvent("InitialChunk", chunk_base_)); |
| 1289 | 1297 |
| 1290 ASSERT(reservation_.IsReserved()); | 1298 ASSERT(reservation_.IsReserved()); |
| 1291 heap()->isolate()->memory_allocator()->FreeMemory(&reservation_, | 1299 heap()->isolate()->memory_allocator()->FreeMemory(&reservation_, |
| 1292 NOT_EXECUTABLE); | 1300 NOT_EXECUTABLE); |
| 1293 chunk_base_ = NULL; | 1301 chunk_base_ = NULL; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1330 if (!from_space_.ShrinkTo(rounded_new_capacity)) { | 1338 if (!from_space_.ShrinkTo(rounded_new_capacity)) { |
| 1331 // If we managed to shrink to-space but couldn't shrink from | 1339 // If we managed to shrink to-space but couldn't shrink from |
| 1332 // space, attempt to grow to-space again. | 1340 // space, attempt to grow to-space again. |
| 1333 if (!to_space_.GrowTo(from_space_.Capacity())) { | 1341 if (!to_space_.GrowTo(from_space_.Capacity())) { |
| 1334 // We are in an inconsistent state because we could not | 1342 // We are in an inconsistent state because we could not |
| 1335 // commit/uncommit memory from new space. | 1343 // commit/uncommit memory from new space. |
| 1336 V8::FatalProcessOutOfMemory("Failed to shrink new space."); | 1344 V8::FatalProcessOutOfMemory("Failed to shrink new space."); |
| 1337 } | 1345 } |
| 1338 } | 1346 } |
| 1339 } | 1347 } |
| 1340 allocation_info_.limit = to_space_.page_high(); | 1348 allocation_info_.set_limit(to_space_.page_high()); |
| 1341 ASSERT_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); | 1349 ASSERT_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); |
| 1342 } | 1350 } |
| 1343 | 1351 |
| 1344 | 1352 |
| 1345 void NewSpace::UpdateAllocationInfo() { | 1353 void NewSpace::UpdateAllocationInfo() { |
| 1346 MemoryChunk::UpdateHighWaterMark(allocation_info_.top); | 1354 MemoryChunk::UpdateHighWaterMark(allocation_info_.top()); |
| 1347 allocation_info_.top = to_space_.page_low(); | 1355 allocation_info_.set_top(to_space_.page_low()); |
| 1348 allocation_info_.limit = to_space_.page_high(); | 1356 allocation_info_.set_limit(to_space_.page_high()); |
| 1349 | 1357 |
| 1350 // Lower limit during incremental marking. | 1358 // Lower limit during incremental marking. |
| 1351 if (heap()->incremental_marking()->IsMarking() && | 1359 if (heap()->incremental_marking()->IsMarking() && |
| 1352 inline_allocation_limit_step() != 0) { | 1360 inline_allocation_limit_step() != 0) { |
| 1353 Address new_limit = | 1361 Address new_limit = |
| 1354 allocation_info_.top + inline_allocation_limit_step(); | 1362 allocation_info_.top() + inline_allocation_limit_step(); |
| 1355 allocation_info_.limit = Min(new_limit, allocation_info_.limit); | 1363 allocation_info_.set_limit(Min(new_limit, allocation_info_.limit())); |
| 1356 } | 1364 } |
| 1357 ASSERT_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); | 1365 ASSERT_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); |
| 1358 } | 1366 } |
| 1359 | 1367 |
| 1360 | 1368 |
| 1361 void NewSpace::ResetAllocationInfo() { | 1369 void NewSpace::ResetAllocationInfo() { |
| 1362 to_space_.Reset(); | 1370 to_space_.Reset(); |
| 1363 UpdateAllocationInfo(); | 1371 UpdateAllocationInfo(); |
| 1364 pages_used_ = 0; | 1372 pages_used_ = 0; |
| 1365 // Clear all mark-bits in the to-space. | 1373 // Clear all mark-bits in the to-space. |
| 1366 NewSpacePageIterator it(&to_space_); | 1374 NewSpacePageIterator it(&to_space_); |
| 1367 while (it.has_next()) { | 1375 while (it.has_next()) { |
| 1368 Bitmap::Clear(it.next()); | 1376 Bitmap::Clear(it.next()); |
| 1369 } | 1377 } |
| 1370 } | 1378 } |
| 1371 | 1379 |
| 1372 | 1380 |
| 1373 bool NewSpace::AddFreshPage() { | 1381 bool NewSpace::AddFreshPage() { |
| 1374 Address top = allocation_info_.top; | 1382 Address top = allocation_info_.top(); |
| 1375 if (NewSpacePage::IsAtStart(top)) { | 1383 if (NewSpacePage::IsAtStart(top)) { |
| 1376 // The current page is already empty. Don't try to make another. | 1384 // The current page is already empty. Don't try to make another. |
| 1377 | 1385 |
| 1378 // We should only get here if someone asks to allocate more | 1386 // We should only get here if someone asks to allocate more |
| 1379 // than what can be stored in a single page. | 1387 // than what can be stored in a single page. |
| 1380 // TODO(gc): Change the limit on new-space allocation to prevent this | 1388 // TODO(gc): Change the limit on new-space allocation to prevent this |
| 1381 // from happening (all such allocations should go directly to LOSpace). | 1389 // from happening (all such allocations should go directly to LOSpace). |
| 1382 return false; | 1390 return false; |
| 1383 } | 1391 } |
| 1384 if (!to_space_.AdvancePage()) { | 1392 if (!to_space_.AdvancePage()) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1396 int remaining_in_page = static_cast<int>(limit - top); | 1404 int remaining_in_page = static_cast<int>(limit - top); |
| 1397 heap()->CreateFillerObjectAt(top, remaining_in_page); | 1405 heap()->CreateFillerObjectAt(top, remaining_in_page); |
| 1398 pages_used_++; | 1406 pages_used_++; |
| 1399 UpdateAllocationInfo(); | 1407 UpdateAllocationInfo(); |
| 1400 | 1408 |
| 1401 return true; | 1409 return true; |
| 1402 } | 1410 } |
| 1403 | 1411 |
| 1404 | 1412 |
| 1405 MaybeObject* NewSpace::SlowAllocateRaw(int size_in_bytes) { | 1413 MaybeObject* NewSpace::SlowAllocateRaw(int size_in_bytes) { |
| 1406 Address old_top = allocation_info_.top; | 1414 Address old_top = allocation_info_.top(); |
| 1407 Address new_top = old_top + size_in_bytes; | 1415 Address new_top = old_top + size_in_bytes; |
| 1408 Address high = to_space_.page_high(); | 1416 Address high = to_space_.page_high(); |
| 1409 if (allocation_info_.limit < high) { | 1417 if (allocation_info_.limit() < high) { |
| 1410 // Incremental marking has lowered the limit to get a | 1418 // Incremental marking has lowered the limit to get a |
| 1411 // chance to do a step. | 1419 // chance to do a step. |
| 1412 allocation_info_.limit = Min( | 1420 Address new_limit = Min( |
| 1413 allocation_info_.limit + inline_allocation_limit_step_, | 1421 allocation_info_.limit() + inline_allocation_limit_step_, |
| 1414 high); | 1422 high); |
| 1423 allocation_info_.set_limit(new_limit); |
| 1415 int bytes_allocated = static_cast<int>(new_top - top_on_previous_step_); | 1424 int bytes_allocated = static_cast<int>(new_top - top_on_previous_step_); |
| 1416 heap()->incremental_marking()->Step( | 1425 heap()->incremental_marking()->Step( |
| 1417 bytes_allocated, IncrementalMarking::GC_VIA_STACK_GUARD); | 1426 bytes_allocated, IncrementalMarking::GC_VIA_STACK_GUARD); |
| 1418 top_on_previous_step_ = new_top; | 1427 top_on_previous_step_ = new_top; |
| 1419 return AllocateRaw(size_in_bytes); | 1428 return AllocateRaw(size_in_bytes); |
| 1420 } else if (AddFreshPage()) { | 1429 } else if (AddFreshPage()) { |
| 1421 // Switched to new page. Try allocating again. | 1430 // Switched to new page. Try allocating again. |
| 1422 int bytes_allocated = static_cast<int>(old_top - top_on_previous_step_); | 1431 int bytes_allocated = static_cast<int>(old_top - top_on_previous_step_); |
| 1423 heap()->incremental_marking()->Step( | 1432 heap()->incremental_marking()->Step( |
| 1424 bytes_allocated, IncrementalMarking::GC_VIA_STACK_GUARD); | 1433 bytes_allocated, IncrementalMarking::GC_VIA_STACK_GUARD); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1513 | 1522 |
| 1514 void SemiSpace::TearDown() { | 1523 void SemiSpace::TearDown() { |
| 1515 start_ = NULL; | 1524 start_ = NULL; |
| 1516 capacity_ = 0; | 1525 capacity_ = 0; |
| 1517 } | 1526 } |
| 1518 | 1527 |
| 1519 | 1528 |
| 1520 bool SemiSpace::Commit() { | 1529 bool SemiSpace::Commit() { |
| 1521 ASSERT(!is_committed()); | 1530 ASSERT(!is_committed()); |
| 1522 int pages = capacity_ / Page::kPageSize; | 1531 int pages = capacity_ / Page::kPageSize; |
| 1523 Address end = start_ + maximum_capacity_; | 1532 if (!heap()->isolate()->memory_allocator()->CommitBlock(start_, |
| 1524 Address start = end - pages * Page::kPageSize; | |
| 1525 if (!heap()->isolate()->memory_allocator()->CommitBlock(start, | |
| 1526 capacity_, | 1533 capacity_, |
| 1527 executable())) { | 1534 executable())) { |
| 1528 return false; | 1535 return false; |
| 1529 } | 1536 } |
| 1530 | 1537 |
| 1531 NewSpacePage* page = anchor(); | 1538 NewSpacePage* current = anchor(); |
| 1532 for (int i = 1; i <= pages; i++) { | 1539 for (int i = 0; i < pages; i++) { |
| 1533 NewSpacePage* new_page = | 1540 NewSpacePage* new_page = |
| 1534 NewSpacePage::Initialize(heap(), end - i * Page::kPageSize, this); | 1541 NewSpacePage::Initialize(heap(), start_ + i * Page::kPageSize, this); |
| 1535 new_page->InsertAfter(page); | 1542 new_page->InsertAfter(current); |
| 1536 page = new_page; | 1543 current = new_page; |
| 1537 } | 1544 } |
| 1538 | 1545 |
| 1539 committed_ = true; | 1546 committed_ = true; |
| 1540 Reset(); | 1547 Reset(); |
| 1541 return true; | 1548 return true; |
| 1542 } | 1549 } |
| 1543 | 1550 |
| 1544 | 1551 |
| 1545 bool SemiSpace::Uncommit() { | 1552 bool SemiSpace::Uncommit() { |
| 1546 ASSERT(is_committed()); | 1553 ASSERT(is_committed()); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1570 bool SemiSpace::GrowTo(int new_capacity) { | 1577 bool SemiSpace::GrowTo(int new_capacity) { |
| 1571 if (!is_committed()) { | 1578 if (!is_committed()) { |
| 1572 if (!Commit()) return false; | 1579 if (!Commit()) return false; |
| 1573 } | 1580 } |
| 1574 ASSERT((new_capacity & Page::kPageAlignmentMask) == 0); | 1581 ASSERT((new_capacity & Page::kPageAlignmentMask) == 0); |
| 1575 ASSERT(new_capacity <= maximum_capacity_); | 1582 ASSERT(new_capacity <= maximum_capacity_); |
| 1576 ASSERT(new_capacity > capacity_); | 1583 ASSERT(new_capacity > capacity_); |
| 1577 int pages_before = capacity_ / Page::kPageSize; | 1584 int pages_before = capacity_ / Page::kPageSize; |
| 1578 int pages_after = new_capacity / Page::kPageSize; | 1585 int pages_after = new_capacity / Page::kPageSize; |
| 1579 | 1586 |
| 1580 Address end = start_ + maximum_capacity_; | |
| 1581 Address start = end - new_capacity; | |
| 1582 size_t delta = new_capacity - capacity_; | 1587 size_t delta = new_capacity - capacity_; |
| 1583 | 1588 |
| 1584 ASSERT(IsAligned(delta, OS::AllocateAlignment())); | 1589 ASSERT(IsAligned(delta, OS::AllocateAlignment())); |
| 1585 if (!heap()->isolate()->memory_allocator()->CommitBlock( | 1590 if (!heap()->isolate()->memory_allocator()->CommitBlock( |
| 1586 start, delta, executable())) { | 1591 start_ + capacity_, delta, executable())) { |
| 1587 return false; | 1592 return false; |
| 1588 } | 1593 } |
| 1589 capacity_ = new_capacity; | 1594 capacity_ = new_capacity; |
| 1590 NewSpacePage* last_page = anchor()->prev_page(); | 1595 NewSpacePage* last_page = anchor()->prev_page(); |
| 1591 ASSERT(last_page != anchor()); | 1596 ASSERT(last_page != anchor()); |
| 1592 for (int i = pages_before + 1; i <= pages_after; i++) { | 1597 for (int i = pages_before; i < pages_after; i++) { |
| 1593 Address page_address = end - i * Page::kPageSize; | 1598 Address page_address = start_ + i * Page::kPageSize; |
| 1594 NewSpacePage* new_page = NewSpacePage::Initialize(heap(), | 1599 NewSpacePage* new_page = NewSpacePage::Initialize(heap(), |
| 1595 page_address, | 1600 page_address, |
| 1596 this); | 1601 this); |
| 1597 new_page->InsertAfter(last_page); | 1602 new_page->InsertAfter(last_page); |
| 1598 Bitmap::Clear(new_page); | 1603 Bitmap::Clear(new_page); |
| 1599 // Duplicate the flags that was set on the old page. | 1604 // Duplicate the flags that was set on the old page. |
| 1600 new_page->SetFlags(last_page->GetFlags(), | 1605 new_page->SetFlags(last_page->GetFlags(), |
| 1601 NewSpacePage::kCopyOnFlipFlagsMask); | 1606 NewSpacePage::kCopyOnFlipFlagsMask); |
| 1602 last_page = new_page; | 1607 last_page = new_page; |
| 1603 } | 1608 } |
| 1604 return true; | 1609 return true; |
| 1605 } | 1610 } |
| 1606 | 1611 |
| 1607 | 1612 |
| 1608 bool SemiSpace::ShrinkTo(int new_capacity) { | 1613 bool SemiSpace::ShrinkTo(int new_capacity) { |
| 1609 ASSERT((new_capacity & Page::kPageAlignmentMask) == 0); | 1614 ASSERT((new_capacity & Page::kPageAlignmentMask) == 0); |
| 1610 ASSERT(new_capacity >= initial_capacity_); | 1615 ASSERT(new_capacity >= initial_capacity_); |
| 1611 ASSERT(new_capacity < capacity_); | 1616 ASSERT(new_capacity < capacity_); |
| 1612 if (is_committed()) { | 1617 if (is_committed()) { |
| 1613 // Semispaces grow backwards from the end of their allocated capacity, | |
| 1614 // so we find the before and after start addresses relative to the | |
| 1615 // end of the space. | |
| 1616 Address space_end = start_ + maximum_capacity_; | |
| 1617 Address old_start = space_end - capacity_; | |
| 1618 size_t delta = capacity_ - new_capacity; | 1618 size_t delta = capacity_ - new_capacity; |
| 1619 ASSERT(IsAligned(delta, OS::AllocateAlignment())); | 1619 ASSERT(IsAligned(delta, OS::AllocateAlignment())); |
| 1620 | 1620 |
| 1621 MemoryAllocator* allocator = heap()->isolate()->memory_allocator(); | 1621 MemoryAllocator* allocator = heap()->isolate()->memory_allocator(); |
| 1622 if (!allocator->UncommitBlock(old_start, delta)) { | 1622 if (!allocator->UncommitBlock(start_ + new_capacity, delta)) { |
| 1623 return false; | 1623 return false; |
| 1624 } | 1624 } |
| 1625 | 1625 |
| 1626 int pages_after = new_capacity / Page::kPageSize; | 1626 int pages_after = new_capacity / Page::kPageSize; |
| 1627 NewSpacePage* new_last_page = | 1627 NewSpacePage* new_last_page = |
| 1628 NewSpacePage::FromAddress(space_end - pages_after * Page::kPageSize); | 1628 NewSpacePage::FromAddress(start_ + (pages_after - 1) * Page::kPageSize); |
| 1629 new_last_page->set_next_page(anchor()); | 1629 new_last_page->set_next_page(anchor()); |
| 1630 anchor()->set_prev_page(new_last_page); | 1630 anchor()->set_prev_page(new_last_page); |
| 1631 ASSERT((current_page_ <= first_page()) && (current_page_ >= new_last_page)); | 1631 ASSERT((current_page_ >= first_page()) && (current_page_ <= new_last_page)); |
| 1632 } | 1632 } |
| 1633 | 1633 |
| 1634 capacity_ = new_capacity; | 1634 capacity_ = new_capacity; |
| 1635 | 1635 |
| 1636 return true; | 1636 return true; |
| 1637 } | 1637 } |
| 1638 | 1638 |
| 1639 | 1639 |
| 1640 void SemiSpace::FlipPages(intptr_t flags, intptr_t mask) { | 1640 void SemiSpace::FlipPages(intptr_t flags, intptr_t mask) { |
| 1641 anchor_.set_owner(this); | 1641 anchor_.set_owner(this); |
| (...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1968 void NewSpace::RecordPromotion(HeapObject* obj) { | 1968 void NewSpace::RecordPromotion(HeapObject* obj) { |
| 1969 InstanceType type = obj->map()->instance_type(); | 1969 InstanceType type = obj->map()->instance_type(); |
| 1970 ASSERT(0 <= type && type <= LAST_TYPE); | 1970 ASSERT(0 <= type && type <= LAST_TYPE); |
| 1971 promoted_histogram_[type].increment_number(1); | 1971 promoted_histogram_[type].increment_number(1); |
| 1972 promoted_histogram_[type].increment_bytes(obj->Size()); | 1972 promoted_histogram_[type].increment_bytes(obj->Size()); |
| 1973 } | 1973 } |
| 1974 | 1974 |
| 1975 | 1975 |
| 1976 size_t NewSpace::CommittedPhysicalMemory() { | 1976 size_t NewSpace::CommittedPhysicalMemory() { |
| 1977 if (!VirtualMemory::HasLazyCommits()) return CommittedMemory(); | 1977 if (!VirtualMemory::HasLazyCommits()) return CommittedMemory(); |
| 1978 MemoryChunk::UpdateHighWaterMark(allocation_info_.top); | 1978 MemoryChunk::UpdateHighWaterMark(allocation_info_.top()); |
| 1979 size_t size = to_space_.CommittedPhysicalMemory(); | 1979 size_t size = to_space_.CommittedPhysicalMemory(); |
| 1980 if (from_space_.is_committed()) { | 1980 if (from_space_.is_committed()) { |
| 1981 size += from_space_.CommittedPhysicalMemory(); | 1981 size += from_space_.CommittedPhysicalMemory(); |
| 1982 } | 1982 } |
| 1983 return size; | 1983 return size; |
| 1984 } | 1984 } |
| 1985 | 1985 |
| 1986 | 1986 |
| 1987 // ----------------------------------------------------------------------------- | 1987 // ----------------------------------------------------------------------------- |
| 1988 // Free lists for old object spaces implementation | 1988 // Free lists for old object spaces implementation |
| (...skipping 505 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2494 // space than the minimum NewSpace size. The limit can be set lower than | 2494 // space than the minimum NewSpace size. The limit can be set lower than |
| 2495 // the end of new space either because there is more space on the next page | 2495 // the end of new space either because there is more space on the next page |
| 2496 // or because we have lowered the limit in order to get periodic incremental | 2496 // or because we have lowered the limit in order to get periodic incremental |
| 2497 // marking. The most reliable way to ensure that there is linear space is | 2497 // marking. The most reliable way to ensure that there is linear space is |
| 2498 // to do the allocation, then rewind the limit. | 2498 // to do the allocation, then rewind the limit. |
| 2499 ASSERT(bytes <= InitialCapacity()); | 2499 ASSERT(bytes <= InitialCapacity()); |
| 2500 MaybeObject* maybe = AllocateRaw(bytes); | 2500 MaybeObject* maybe = AllocateRaw(bytes); |
| 2501 Object* object = NULL; | 2501 Object* object = NULL; |
| 2502 if (!maybe->ToObject(&object)) return false; | 2502 if (!maybe->ToObject(&object)) return false; |
| 2503 HeapObject* allocation = HeapObject::cast(object); | 2503 HeapObject* allocation = HeapObject::cast(object); |
| 2504 Address top = allocation_info_.top; | 2504 Address top = allocation_info_.top(); |
| 2505 if ((top - bytes) == allocation->address()) { | 2505 if ((top - bytes) == allocation->address()) { |
| 2506 allocation_info_.top = allocation->address(); | 2506 allocation_info_.set_top(allocation->address()); |
| 2507 return true; | 2507 return true; |
| 2508 } | 2508 } |
| 2509 // There may be a borderline case here where the allocation succeeded, but | 2509 // There may be a borderline case here where the allocation succeeded, but |
| 2510 // the limit and top have moved on to a new page. In that case we try again. | 2510 // the limit and top have moved on to a new page. In that case we try again. |
| 2511 return ReserveSpace(bytes); | 2511 return ReserveSpace(bytes); |
| 2512 } | 2512 } |
| 2513 | 2513 |
| 2514 | 2514 |
| 2515 void PagedSpace::PrepareForMarkCompact() { | 2515 void PagedSpace::PrepareForMarkCompact() { |
| 2516 // We don't have a linear allocation area while sweeping. It will be restored | 2516 // We don't have a linear allocation area while sweeping. It will be restored |
| (...skipping 25 matching lines...) Expand all Loading... |
| 2542 unswept_free_bytes_ = 0; | 2542 unswept_free_bytes_ = 0; |
| 2543 | 2543 |
| 2544 // Clear the free list before a full GC---it will be rebuilt afterward. | 2544 // Clear the free list before a full GC---it will be rebuilt afterward. |
| 2545 free_list_.Reset(); | 2545 free_list_.Reset(); |
| 2546 } | 2546 } |
| 2547 | 2547 |
| 2548 | 2548 |
| 2549 bool PagedSpace::ReserveSpace(int size_in_bytes) { | 2549 bool PagedSpace::ReserveSpace(int size_in_bytes) { |
| 2550 ASSERT(size_in_bytes <= AreaSize()); | 2550 ASSERT(size_in_bytes <= AreaSize()); |
| 2551 ASSERT(size_in_bytes == RoundSizeDownToObjectAlignment(size_in_bytes)); | 2551 ASSERT(size_in_bytes == RoundSizeDownToObjectAlignment(size_in_bytes)); |
| 2552 Address current_top = allocation_info_.top; | 2552 Address current_top = allocation_info_.top(); |
| 2553 Address new_top = current_top + size_in_bytes; | 2553 Address new_top = current_top + size_in_bytes; |
| 2554 if (new_top <= allocation_info_.limit) return true; | 2554 if (new_top <= allocation_info_.limit()) return true; |
| 2555 | 2555 |
| 2556 HeapObject* new_area = free_list_.Allocate(size_in_bytes); | 2556 HeapObject* new_area = free_list_.Allocate(size_in_bytes); |
| 2557 if (new_area == NULL) new_area = SlowAllocateRaw(size_in_bytes); | 2557 if (new_area == NULL) new_area = SlowAllocateRaw(size_in_bytes); |
| 2558 if (new_area == NULL) return false; | 2558 if (new_area == NULL) return false; |
| 2559 | 2559 |
| 2560 int old_linear_size = static_cast<int>(limit() - top()); | 2560 int old_linear_size = static_cast<int>(limit() - top()); |
| 2561 // Mark the old linear allocation area with a free space so it can be | 2561 // Mark the old linear allocation area with a free space so it can be |
| 2562 // skipped when scanning the heap. This also puts it back in the free list | 2562 // skipped when scanning the heap. This also puts it back in the free list |
| 2563 // if it is big enough. | 2563 // if it is big enough. |
| 2564 Free(top(), old_linear_size); | 2564 Free(top(), old_linear_size); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2619 first_unswept_page_ = p; | 2619 first_unswept_page_ = p; |
| 2620 } | 2620 } |
| 2621 | 2621 |
| 2622 heap()->FreeQueuedChunks(); | 2622 heap()->FreeQueuedChunks(); |
| 2623 | 2623 |
| 2624 return IsLazySweepingComplete(); | 2624 return IsLazySweepingComplete(); |
| 2625 } | 2625 } |
| 2626 | 2626 |
| 2627 | 2627 |
| 2628 void PagedSpace::EvictEvacuationCandidatesFromFreeLists() { | 2628 void PagedSpace::EvictEvacuationCandidatesFromFreeLists() { |
| 2629 if (allocation_info_.top >= allocation_info_.limit) return; | 2629 if (allocation_info_.top() >= allocation_info_.limit()) return; |
| 2630 | 2630 |
| 2631 if (Page::FromAllocationTop(allocation_info_.top)->IsEvacuationCandidate()) { | 2631 if (Page::FromAllocationTop(allocation_info_.top())-> |
| 2632 IsEvacuationCandidate()) { |
| 2632 // Create filler object to keep page iterable if it was iterable. | 2633 // Create filler object to keep page iterable if it was iterable. |
| 2633 int remaining = | 2634 int remaining = |
| 2634 static_cast<int>(allocation_info_.limit - allocation_info_.top); | 2635 static_cast<int>(allocation_info_.limit() - allocation_info_.top()); |
| 2635 heap()->CreateFillerObjectAt(allocation_info_.top, remaining); | 2636 heap()->CreateFillerObjectAt(allocation_info_.top(), remaining); |
| 2636 | 2637 |
| 2637 allocation_info_.top = NULL; | 2638 allocation_info_.set_top(NULL); |
| 2638 allocation_info_.limit = NULL; | 2639 allocation_info_.set_limit(NULL); |
| 2639 } | 2640 } |
| 2640 } | 2641 } |
| 2641 | 2642 |
| 2642 | 2643 |
| 2643 bool PagedSpace::EnsureSweeperProgress(intptr_t size_in_bytes) { | 2644 bool PagedSpace::EnsureSweeperProgress(intptr_t size_in_bytes) { |
| 2644 MarkCompactCollector* collector = heap()->mark_compact_collector(); | 2645 MarkCompactCollector* collector = heap()->mark_compact_collector(); |
| 2645 if (collector->AreSweeperThreadsActivated()) { | 2646 if (collector->AreSweeperThreadsActivated()) { |
| 2646 if (collector->IsConcurrentSweepingInProgress()) { | 2647 if (collector->IsConcurrentSweepingInProgress()) { |
| 2647 if (collector->StealMemoryFromSweeperThreads(this) < size_in_bytes) { | 2648 if (collector->StealMemoryFromSweeperThreads(this) < size_in_bytes) { |
| 2648 if (!collector->sequential_sweeping()) { | 2649 if (!collector->sequential_sweeping()) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 2678 // Free list allocation failed and there is no next page. Fail if we have | 2679 // Free list allocation failed and there is no next page. Fail if we have |
| 2679 // hit the old generation size limit that should cause a garbage | 2680 // hit the old generation size limit that should cause a garbage |
| 2680 // collection. | 2681 // collection. |
| 2681 if (!heap()->always_allocate() && | 2682 if (!heap()->always_allocate() && |
| 2682 heap()->OldGenerationAllocationLimitReached()) { | 2683 heap()->OldGenerationAllocationLimitReached()) { |
| 2683 return NULL; | 2684 return NULL; |
| 2684 } | 2685 } |
| 2685 | 2686 |
| 2686 // Try to expand the space and allocate in the new next page. | 2687 // Try to expand the space and allocate in the new next page. |
| 2687 if (Expand()) { | 2688 if (Expand()) { |
| 2689 ASSERT(CountTotalPages() > 1 || size_in_bytes <= free_list_.available()); |
| 2688 return free_list_.Allocate(size_in_bytes); | 2690 return free_list_.Allocate(size_in_bytes); |
| 2689 } | 2691 } |
| 2690 | 2692 |
| 2691 // Last ditch, sweep all the remaining pages to try to find space. This may | 2693 // Last ditch, sweep all the remaining pages to try to find space. This may |
| 2692 // cause a pause. | 2694 // cause a pause. |
| 2693 if (!IsLazySweepingComplete()) { | 2695 if (!IsLazySweepingComplete()) { |
| 2694 EnsureSweeperProgress(kMaxInt); | 2696 EnsureSweeperProgress(kMaxInt); |
| 2695 | 2697 |
| 2696 // Retry the free list allocation. | 2698 // Retry the free list allocation. |
| 2697 HeapObject* object = free_list_.Allocate(size_in_bytes); | 2699 HeapObject* object = free_list_.Allocate(size_in_bytes); |
| (...skipping 523 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3221 object->ShortPrint(); | 3223 object->ShortPrint(); |
| 3222 PrintF("\n"); | 3224 PrintF("\n"); |
| 3223 } | 3225 } |
| 3224 printf(" --------------------------------------\n"); | 3226 printf(" --------------------------------------\n"); |
| 3225 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); | 3227 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); |
| 3226 } | 3228 } |
| 3227 | 3229 |
| 3228 #endif // DEBUG | 3230 #endif // DEBUG |
| 3229 | 3231 |
| 3230 } } // namespace v8::internal | 3232 } } // namespace v8::internal |
| OLD | NEW |