Chromium Code Reviews| 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 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 53 #endif | 53 #endif |
| 54 | 54 |
| 55 | 55 |
| 56 namespace v8 { | 56 namespace v8 { |
| 57 namespace internal { | 57 namespace internal { |
| 58 | 58 |
| 59 | 59 |
| 60 String* Heap::hidden_symbol_; | 60 String* Heap::hidden_symbol_; |
| 61 Object* Heap::roots_[Heap::kRootListLength]; | 61 Object* Heap::roots_[Heap::kRootListLength]; |
| 62 Object* Heap::global_contexts_list_; | 62 Object* Heap::global_contexts_list_; |
| 63 StoreBufferRebuilder Heap::store_buffer_rebuilder_; | |
| 63 | 64 |
| 64 | 65 |
| 65 NewSpace Heap::new_space_; | 66 NewSpace Heap::new_space_; |
| 66 OldSpace* Heap::old_pointer_space_ = NULL; | 67 OldSpace* Heap::old_pointer_space_ = NULL; |
| 67 OldSpace* Heap::old_data_space_ = NULL; | 68 OldSpace* Heap::old_data_space_ = NULL; |
| 68 OldSpace* Heap::code_space_ = NULL; | 69 OldSpace* Heap::code_space_ = NULL; |
| 69 MapSpace* Heap::map_space_ = NULL; | 70 MapSpace* Heap::map_space_ = NULL; |
| 70 CellSpace* Heap::cell_space_ = NULL; | 71 CellSpace* Heap::cell_space_ = NULL; |
| 71 LargeObjectSpace* Heap::lo_space_ = NULL; | 72 LargeObjectSpace* Heap::lo_space_ = NULL; |
| 72 | 73 |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 89 int Heap::initial_semispace_size_ = 128*KB; | 90 int Heap::initial_semispace_size_ = 128*KB; |
| 90 intptr_t Heap::code_range_size_ = 0; | 91 intptr_t Heap::code_range_size_ = 0; |
| 91 intptr_t Heap::max_executable_size_ = max_old_generation_size_; | 92 intptr_t Heap::max_executable_size_ = max_old_generation_size_; |
| 92 #elif defined(V8_TARGET_ARCH_X64) | 93 #elif defined(V8_TARGET_ARCH_X64) |
| 93 static const int default_max_semispace_size_ = 16*MB; | 94 static const int default_max_semispace_size_ = 16*MB; |
| 94 intptr_t Heap::max_old_generation_size_ = 1*GB; | 95 intptr_t Heap::max_old_generation_size_ = 1*GB; |
| 95 int Heap::initial_semispace_size_ = 1*MB; | 96 int Heap::initial_semispace_size_ = 1*MB; |
| 96 intptr_t Heap::code_range_size_ = 512*MB; | 97 intptr_t Heap::code_range_size_ = 512*MB; |
| 97 intptr_t Heap::max_executable_size_ = 256*MB; | 98 intptr_t Heap::max_executable_size_ = 256*MB; |
| 98 #else | 99 #else |
| 99 static const int default_max_semispace_size_ = 8*MB; | 100 static const int default_max_semispace_size_ = 4*MB; |
| 100 intptr_t Heap::max_old_generation_size_ = 512*MB; | 101 intptr_t Heap::max_old_generation_size_ = 512*MB; |
| 101 int Heap::initial_semispace_size_ = 512*KB; | 102 int Heap::initial_semispace_size_ = 512*KB; |
| 102 intptr_t Heap::code_range_size_ = 0; | 103 intptr_t Heap::code_range_size_ = 0; |
| 103 intptr_t Heap::max_executable_size_ = 128*MB; | 104 intptr_t Heap::max_executable_size_ = 128*MB; |
| 104 #endif | 105 #endif |
| 105 | 106 |
| 106 // Allow build-time customization of the max semispace size. Building | 107 // Allow build-time customization of the max semispace size. Building |
| 107 // V8 with snapshots and a non-default max semispace size is much | 108 // V8 with snapshots and a non-default max semispace size is much |
| 108 // easier if you can define it as part of the build environment. | 109 // easier if you can define it as part of the build environment. |
| 109 #if defined(V8_MAX_SEMISPACE_SIZE) | 110 #if defined(V8_MAX_SEMISPACE_SIZE) |
| (...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 473 if (collector == SCAVENGER && | 474 if (collector == SCAVENGER && |
| 474 IncrementalMarking::state() != IncrementalMarking::STOPPED) { | 475 IncrementalMarking::state() != IncrementalMarking::STOPPED) { |
| 475 if (FLAG_trace_incremental_marking) { | 476 if (FLAG_trace_incremental_marking) { |
| 476 PrintF("[IncrementalMarking] Scavenge during marking.\n"); | 477 PrintF("[IncrementalMarking] Scavenge during marking.\n"); |
| 477 } | 478 } |
| 478 } | 479 } |
| 479 | 480 |
| 480 if (collector == MARK_COMPACTOR && | 481 if (collector == MARK_COMPACTOR && |
| 481 !MarkCompactCollector::PreciseSweepingRequired() && | 482 !MarkCompactCollector::PreciseSweepingRequired() && |
| 482 IncrementalMarking::state() == IncrementalMarking::MARKING && | 483 IncrementalMarking::state() == IncrementalMarking::MARKING && |
| 484 !IncrementalMarking::should_hurry() && | |
| 483 FLAG_incremental_marking_steps) { | 485 FLAG_incremental_marking_steps) { |
| 484 if (FLAG_trace_incremental_marking) { | 486 if (FLAG_trace_incremental_marking) { |
| 485 PrintF("[IncrementalMarking] Delaying MarkSweep.\n"); | 487 PrintF("[IncrementalMarking] Delaying MarkSweep.\n"); |
| 486 } | 488 } |
| 487 collector = SCAVENGER; | 489 collector = SCAVENGER; |
| 488 } | 490 } |
| 489 | 491 |
| 492 IncrementalMarking::set_should_hurry(false); | |
|
Vyacheslav Egorov (Chromium)
2011/03/28 15:13:19
I think nicer place to clean the flag is in the In
Erik Corry
2011/03/28 15:56:07
Done and made it private.
| |
| 493 | |
| 490 bool next_gc_likely_to_collect_more = false; | 494 bool next_gc_likely_to_collect_more = false; |
| 491 | 495 |
| 492 { GCTracer tracer; | 496 { GCTracer tracer; |
| 493 GarbageCollectionPrologue(); | 497 GarbageCollectionPrologue(); |
| 494 // The GC count was incremented in the prologue. Tell the tracer about | 498 // The GC count was incremented in the prologue. Tell the tracer about |
| 495 // it. | 499 // it. |
| 496 tracer.set_gc_count(gc_count_); | 500 tracer.set_gc_count(gc_count_); |
| 497 | 501 |
| 498 // Tell the tracer which collector we've selected. | 502 // Tell the tracer which collector we've selected. |
| 499 tracer.set_collector(collector); | 503 tracer.set_collector(collector); |
| (...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 944 if (new_space_.Capacity() < new_space_.MaximumCapacity() && | 948 if (new_space_.Capacity() < new_space_.MaximumCapacity() && |
| 945 survived_since_last_expansion_ > new_space_.Capacity()) { | 949 survived_since_last_expansion_ > new_space_.Capacity()) { |
| 946 // Grow the size of new space if there is room to grow and enough | 950 // Grow the size of new space if there is room to grow and enough |
| 947 // data has survived scavenge since the last expansion. | 951 // data has survived scavenge since the last expansion. |
| 948 new_space_.Grow(); | 952 new_space_.Grow(); |
| 949 survived_since_last_expansion_ = 0; | 953 survived_since_last_expansion_ = 0; |
| 950 } | 954 } |
| 951 } | 955 } |
| 952 | 956 |
| 953 | 957 |
| 958 void Heap::ScavengeStoreBufferCallback(MemoryChunk* page, | |
| 959 StoreBufferEvent event) { | |
| 960 store_buffer_rebuilder_.Callback(page, event); | |
| 961 } | |
| 962 | |
| 963 | |
| 964 void StoreBufferRebuilder::Callback(MemoryChunk* page, StoreBufferEvent event) { | |
| 965 if (event == kStoreBufferStartScanningPagesEvent) { | |
| 966 start_of_current_page_ = NULL; | |
| 967 current_page_ = NULL; | |
| 968 } else if (event == kStoreBufferScanningPageEvent) { | |
| 969 if (current_page_ != NULL) { | |
| 970 // If this page already overflowed the store buffer during this iteration. | |
| 971 if (current_page_->scan_on_scavenge()) { | |
| 972 // Then we should wipe out the entries that have been added for it. | |
| 973 StoreBuffer::SetTop(start_of_current_page_); | |
| 974 } else if (StoreBuffer::Top() - start_of_current_page_ >= | |
| 975 (StoreBuffer::Limit() - StoreBuffer::Top()) >> 2) { | |
| 976 // Did we find too many pointers in the previous page? The heuristic is | |
| 977 // that no page can take more then 1/5 the remaining slots in the store | |
| 978 // buffer. | |
| 979 current_page_->set_scan_on_scavenge(true); | |
| 980 StoreBuffer::SetTop(start_of_current_page_); | |
| 981 } else { | |
| 982 // In this case the page we scanned took a reasonable number of slots in | |
| 983 // the store buffer. It has now been rehabilitated and is no longer | |
| 984 // marked scan_on_scavenge. | |
| 985 ASSERT(!current_page_->scan_on_scavenge()); | |
| 986 } | |
| 987 } | |
| 988 start_of_current_page_ = StoreBuffer::Top(); | |
| 989 current_page_ = page; | |
| 990 } else if (event == kStoreBufferFullEvent) { | |
| 991 // The current page overflowed the store buffer again. Wipe out its entries | |
| 992 // in the store buffer and mark it scan-on-scavenge again. This may happen | |
| 993 // several times while scanning. | |
| 994 if (current_page_ == NULL) { | |
| 995 // Store Buffer overflowed while scanning promoted objects. These are not | |
| 996 // in any particular page, though they are likely to be clustered by the | |
| 997 // allocation routines. | |
| 998 StoreBuffer::HandleFullness(); | |
| 999 } else { | |
| 1000 // Store Buffer overflowed while scanning a particular old space page for | |
| 1001 // pointers to new space. | |
| 1002 ASSERT(current_page_ == page); | |
| 1003 ASSERT(page != NULL); | |
| 1004 current_page_->set_scan_on_scavenge(true); | |
| 1005 ASSERT(start_of_current_page_ != StoreBuffer::Top()); | |
| 1006 StoreBuffer::SetTop(start_of_current_page_); | |
| 1007 } | |
| 1008 } else { | |
| 1009 UNREACHABLE(); | |
| 1010 } | |
| 1011 } | |
| 1012 | |
| 1013 | |
| 954 void Heap::Scavenge() { | 1014 void Heap::Scavenge() { |
| 955 #ifdef DEBUG | 1015 #ifdef DEBUG |
| 956 if (FLAG_enable_slow_asserts) VerifyNonPointerSpacePointers(); | 1016 if (FLAG_enable_slow_asserts) VerifyNonPointerSpacePointers(); |
| 957 #endif | 1017 #endif |
| 958 | 1018 |
| 959 gc_state_ = SCAVENGE; | 1019 gc_state_ = SCAVENGE; |
| 960 | 1020 |
| 961 // Implements Cheney's copying algorithm | 1021 // Implements Cheney's copying algorithm |
| 962 LOG(ResourceEvent("scavenge", "begin")); | 1022 LOG(ResourceEvent("scavenge", "begin")); |
| 963 | 1023 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1001 #ifdef DEBUG | 1061 #ifdef DEBUG |
| 1002 StoreBuffer::Clean(); | 1062 StoreBuffer::Clean(); |
| 1003 #endif | 1063 #endif |
| 1004 | 1064 |
| 1005 ScavengeVisitor scavenge_visitor; | 1065 ScavengeVisitor scavenge_visitor; |
| 1006 // Copy roots. | 1066 // Copy roots. |
| 1007 IterateRoots(&scavenge_visitor, VISIT_ALL_IN_SCAVENGE); | 1067 IterateRoots(&scavenge_visitor, VISIT_ALL_IN_SCAVENGE); |
| 1008 | 1068 |
| 1009 // Copy objects reachable from the old generation. | 1069 // Copy objects reachable from the old generation. |
| 1010 { | 1070 { |
| 1011 StoreBufferRebuildScope scope; | 1071 StoreBufferRebuildScope scope(&ScavengeStoreBufferCallback); |
| 1012 StoreBuffer::IteratePointersToNewSpace(&ScavengeObject); | 1072 StoreBuffer::IteratePointersToNewSpace(&ScavengeObject); |
| 1013 } | 1073 } |
| 1014 | 1074 |
| 1015 // Copy objects reachable from cells by scavenging cell values directly. | 1075 // Copy objects reachable from cells by scavenging cell values directly. |
| 1016 HeapObjectIterator cell_iterator(cell_space_); | 1076 HeapObjectIterator cell_iterator(cell_space_); |
| 1017 for (HeapObject* cell = cell_iterator.Next(); | 1077 for (HeapObject* cell = cell_iterator.Next(); |
| 1018 cell != NULL; cell = cell_iterator.Next()) { | 1078 cell != NULL; cell = cell_iterator.Next()) { |
| 1019 if (cell->IsJSGlobalPropertyCell()) { | 1079 if (cell->IsJSGlobalPropertyCell()) { |
| 1020 Address value_address = | 1080 Address value_address = |
| 1021 reinterpret_cast<Address>(cell) + | 1081 reinterpret_cast<Address>(cell) + |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1198 // The addresses new_space_front and new_space_.top() define a | 1258 // The addresses new_space_front and new_space_.top() define a |
| 1199 // queue of unprocessed copied objects. Process them until the | 1259 // queue of unprocessed copied objects. Process them until the |
| 1200 // queue is empty. | 1260 // queue is empty. |
| 1201 while (new_space_front < new_space_.top()) { | 1261 while (new_space_front < new_space_.top()) { |
| 1202 HeapObject* object = HeapObject::FromAddress(new_space_front); | 1262 HeapObject* object = HeapObject::FromAddress(new_space_front); |
| 1203 new_space_front += NewSpaceScavenger::IterateBody(object->map(), object); | 1263 new_space_front += NewSpaceScavenger::IterateBody(object->map(), object); |
| 1204 } | 1264 } |
| 1205 | 1265 |
| 1206 // Promote and process all the to-be-promoted objects. | 1266 // Promote and process all the to-be-promoted objects. |
| 1207 { | 1267 { |
| 1208 StoreBufferRebuildScope scope; | 1268 StoreBufferRebuildScope scope(&ScavengeStoreBufferCallback); |
| 1209 while (!promotion_queue.is_empty()) { | 1269 while (!promotion_queue.is_empty()) { |
| 1210 HeapObject* target; | 1270 HeapObject* target; |
| 1211 int size; | 1271 int size; |
| 1212 promotion_queue.remove(&target, &size); | 1272 promotion_queue.remove(&target, &size); |
| 1213 | 1273 |
| 1214 // Promoted object might be already partially visited | 1274 // Promoted object might be already partially visited |
| 1215 // during old space pointer iteration. Thus we search specificly | 1275 // during old space pointer iteration. Thus we search specificly |
| 1216 // for pointers to from semispace instead of looking for pointers | 1276 // for pointers to from semispace instead of looking for pointers |
| 1217 // to new space. | 1277 // to new space. |
| 1218 ASSERT(!target->IsMap()); | 1278 ASSERT(!target->IsMap()); |
| (...skipping 2751 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3970 } | 4030 } |
| 3971 | 4031 |
| 3972 | 4032 |
| 3973 static void VerifyPointers( | 4033 static void VerifyPointers( |
| 3974 PagedSpace* space, | 4034 PagedSpace* space, |
| 3975 PointerRegionCallback visit_pointer_region) { | 4035 PointerRegionCallback visit_pointer_region) { |
| 3976 PageIterator it(space); | 4036 PageIterator it(space); |
| 3977 | 4037 |
| 3978 while (it.has_next()) { | 4038 while (it.has_next()) { |
| 3979 Page* page = it.next(); | 4039 Page* page = it.next(); |
| 3980 Address start = page->ObjectAreaStart(); | 4040 Heap::IteratePointersOnPage( |
| 3981 Address end = page->ObjectAreaEnd(); | 4041 reinterpret_cast<PagedSpace*>(page->owner()), |
| 3982 | 4042 &Heap::IteratePointersToNewSpace, |
| 3983 Heap::IteratePointersToNewSpace(start, | 4043 &DummyScavengePointer, |
| 3984 end, | 4044 page); |
| 3985 &DummyScavengePointer); | |
| 3986 } | 4045 } |
| 3987 } | 4046 } |
| 3988 | 4047 |
| 3989 | 4048 |
| 3990 static void VerifyPointers(LargeObjectSpace* space) { | 4049 static void VerifyPointers(LargeObjectSpace* space) { |
| 3991 LargeObjectIterator it(space); | 4050 LargeObjectIterator it(space); |
| 3992 for (HeapObject* object = it.next(); object != NULL; object = it.next()) { | 4051 for (HeapObject* object = it.next(); object != NULL; object = it.next()) { |
| 3993 if (object->IsFixedArray()) { | 4052 if (object->IsFixedArray()) { |
| 3994 Address slot_address = object->address(); | 4053 Address slot_address = object->address(); |
| 3995 Address end = object->address() + object->Size(); | 4054 Address end = object->address() + object->Size(); |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4186 } | 4245 } |
| 4187 | 4246 |
| 4188 | 4247 |
| 4189 void Heap::IterateAndMarkPointersToFromSpace(Address start, | 4248 void Heap::IterateAndMarkPointersToFromSpace(Address start, |
| 4190 Address end, | 4249 Address end, |
| 4191 ObjectSlotCallback callback) { | 4250 ObjectSlotCallback callback) { |
| 4192 Address slot_address = start; | 4251 Address slot_address = start; |
| 4193 while (slot_address < end) { | 4252 while (slot_address < end) { |
| 4194 Object** slot = reinterpret_cast<Object**>(slot_address); | 4253 Object** slot = reinterpret_cast<Object**>(slot_address); |
| 4195 Object* object = *slot; | 4254 Object* object = *slot; |
| 4196 // In normal store buffer operation we use this function to process the | 4255 // If the store buffer becomes overfull we mark pages as being exempt from |
| 4197 // promotion queue and we never scan an object twice so we will not see | 4256 // the store buffer. These pages are scanned to find pointers that point |
| 4198 // pointers that have already been updated to point to to-space. But | 4257 // to the new space. In that case we may hit newly promoted objects and |
| 4199 // in the case of store buffer overflow we scan the entire old space to | 4258 // fix the pointers before the promotion queue gets to them. Thus the 'if'. |
| 4200 // find pointers that point to new-space and in that case we may hit | |
| 4201 // newly promoted objects and fix the pointers before the promotion | |
| 4202 // queue gets to them. | |
| 4203 ASSERT(StoreBuffer::store_buffer_mode() != | |
| 4204 StoreBuffer::kStoreBufferFunctional || | |
| 4205 !Heap::InToSpace(object)); | |
| 4206 if (Heap::InFromSpace(object)) { | 4259 if (Heap::InFromSpace(object)) { |
| 4207 callback(reinterpret_cast<HeapObject**>(slot), HeapObject::cast(object)); | 4260 callback(reinterpret_cast<HeapObject**>(slot), HeapObject::cast(object)); |
| 4208 if (Heap::InNewSpace(*slot)) { | 4261 if (Heap::InNewSpace(*slot)) { |
| 4209 ASSERT(Heap::InToSpace(*slot)); | 4262 ASSERT(Heap::InToSpace(*slot)); |
| 4210 ASSERT((*slot)->IsHeapObject()); | 4263 ASSERT((*slot)->IsHeapObject()); |
| 4211 ASSERT(StoreBuffer::CellIsInStoreBuffer( | |
| 4212 reinterpret_cast<Address>(slot))); | |
| 4213 } | 4264 } |
| 4214 } | 4265 } |
| 4215 slot_address += kPointerSize; | 4266 slot_address += kPointerSize; |
| 4216 } | 4267 } |
| 4217 } | 4268 } |
| 4218 | 4269 |
| 4219 | 4270 |
| 4220 #ifdef DEBUG | 4271 #ifdef DEBUG |
| 4221 typedef bool (*CheckStoreBufferFilter)(Object** addr); | 4272 typedef bool (*CheckStoreBufferFilter)(Object** addr); |
| 4222 | 4273 |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4283 while (!(*obj_start)->IsMap()) obj_start--; | 4334 while (!(*obj_start)->IsMap()) obj_start--; |
| 4284 UNREACHABLE(); | 4335 UNREACHABLE(); |
| 4285 } | 4336 } |
| 4286 } | 4337 } |
| 4287 } | 4338 } |
| 4288 | 4339 |
| 4289 | 4340 |
| 4290 // Check that the store buffer contains all intergenerational pointers by | 4341 // Check that the store buffer contains all intergenerational pointers by |
| 4291 // scanning a page and ensuring that all pointers to young space are in the | 4342 // scanning a page and ensuring that all pointers to young space are in the |
| 4292 // store buffer. | 4343 // store buffer. |
| 4293 void Heap::OldPointerSpaceCheckStoreBuffer( | 4344 void Heap::OldPointerSpaceCheckStoreBuffer() { |
| 4294 ExpectedPageWatermarkState watermark_state) { | |
| 4295 OldSpace* space = old_pointer_space(); | 4345 OldSpace* space = old_pointer_space(); |
| 4296 PageIterator pages(space); | 4346 PageIterator pages(space); |
| 4297 | 4347 |
| 4298 StoreBuffer::SortUniq(); | 4348 StoreBuffer::SortUniq(); |
| 4299 | 4349 |
| 4300 while (pages.has_next()) { | 4350 while (pages.has_next()) { |
| 4301 Page* page = pages.next(); | 4351 Page* page = pages.next(); |
| 4302 Object** current = reinterpret_cast<Object**>(page->ObjectAreaStart()); | 4352 Object** current = reinterpret_cast<Object**>(page->ObjectAreaStart()); |
| 4303 | 4353 |
| 4304 Address end = page->ObjectAreaEnd(); | 4354 Address end = page->ObjectAreaEnd(); |
| 4305 | 4355 |
| 4306 Object*** store_buffer_position = StoreBuffer::Start(); | 4356 Object*** store_buffer_position = StoreBuffer::Start(); |
| 4307 Object*** store_buffer_top = StoreBuffer::Top(); | 4357 Object*** store_buffer_top = StoreBuffer::Top(); |
| 4308 | 4358 |
| 4309 Object** limit = reinterpret_cast<Object**>(end); | 4359 Object** limit = reinterpret_cast<Object**>(end); |
| 4310 CheckStoreBuffer(current, | 4360 CheckStoreBuffer(current, |
| 4311 limit, | 4361 limit, |
| 4312 &store_buffer_position, | 4362 &store_buffer_position, |
| 4313 store_buffer_top, | 4363 store_buffer_top, |
| 4314 &EverythingsAPointer, | 4364 &EverythingsAPointer, |
| 4315 space->top(), | 4365 space->top(), |
| 4316 space->limit()); | 4366 space->limit()); |
| 4317 } | 4367 } |
| 4318 } | 4368 } |
| 4319 | 4369 |
| 4320 | 4370 |
| 4321 void Heap::MapSpaceCheckStoreBuffer( | 4371 void Heap::MapSpaceCheckStoreBuffer() { |
| 4322 ExpectedPageWatermarkState watermark_state) { | |
| 4323 MapSpace* space = map_space(); | 4372 MapSpace* space = map_space(); |
| 4324 PageIterator pages(space); | 4373 PageIterator pages(space); |
| 4325 | 4374 |
| 4326 StoreBuffer::SortUniq(); | 4375 StoreBuffer::SortUniq(); |
| 4327 | 4376 |
| 4328 while (pages.has_next()) { | 4377 while (pages.has_next()) { |
| 4329 Page* page = pages.next(); | 4378 Page* page = pages.next(); |
| 4330 Object** current = reinterpret_cast<Object**>(page->ObjectAreaStart()); | 4379 Object** current = reinterpret_cast<Object**>(page->ObjectAreaStart()); |
| 4331 | 4380 |
| 4332 Address end = page->ObjectAreaEnd(); | 4381 Address end = page->ObjectAreaEnd(); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4383 // be marked with a free space or filler. Because the free space and filler | 4432 // be marked with a free space or filler. Because the free space and filler |
| 4384 // maps do not move we can always recognize these even after a compaction. | 4433 // maps do not move we can always recognize these even after a compaction. |
| 4385 // Normal objects like FixedArrays and JSObjects should not contain references | 4434 // Normal objects like FixedArrays and JSObjects should not contain references |
| 4386 // to these maps. The special garbage section (see comment in spaces.h) is | 4435 // to these maps. The special garbage section (see comment in spaces.h) is |
| 4387 // skipped since it can contain absolutely anything. Any objects that are | 4436 // skipped since it can contain absolutely anything. Any objects that are |
| 4388 // allocated during iteration may or may not be visited by the iteration, but | 4437 // allocated during iteration may or may not be visited by the iteration, but |
| 4389 // they will not be partially visited. | 4438 // they will not be partially visited. |
| 4390 void Heap::IteratePointers( | 4439 void Heap::IteratePointers( |
| 4391 PagedSpace* space, | 4440 PagedSpace* space, |
| 4392 PointerRegionCallback visit_pointer_region, | 4441 PointerRegionCallback visit_pointer_region, |
| 4393 ObjectSlotCallback copy_object_func, | 4442 ObjectSlotCallback copy_object_func) { |
| 4394 ExpectedPageWatermarkState expected_page_watermark_state) { | |
| 4395 | 4443 |
| 4396 PageIterator pages(space); | 4444 PageIterator pages(space); |
| 4397 | 4445 |
| 4398 while (pages.has_next()) { | 4446 while (pages.has_next()) { |
| 4399 Page* page = pages.next(); | 4447 Page* page = pages.next(); |
| 4400 Address start = page->ObjectAreaStart(); | 4448 IteratePointersOnPage(space, visit_pointer_region, copy_object_func, page); |
| 4401 Address limit = page->ObjectAreaEnd(); | |
| 4402 | |
| 4403 Address end = start; | |
| 4404 | |
| 4405 Object* free_space_map = Heap::free_space_map(); | |
| 4406 Object* two_pointer_filler_map = Heap::two_pointer_filler_map(); | |
| 4407 | |
| 4408 while (end < limit) { | |
| 4409 Object* o = *reinterpret_cast<Object**>(end); | |
| 4410 // Skip fillers but not things that look like fillers in the special | |
| 4411 // garbage section which can contain anything. | |
| 4412 if (o == free_space_map || | |
| 4413 o == two_pointer_filler_map || | |
| 4414 end == space->top()) { | |
| 4415 if (start != end) { | |
| 4416 // After calling this the special garbage section may have moved. | |
| 4417 visit_pointer_region(start, end, copy_object_func); | |
| 4418 if (end >= space->top() && end < space->limit()) { | |
| 4419 end = space->limit(); | |
| 4420 start = end; | |
| 4421 continue; | |
| 4422 } | |
| 4423 } | |
| 4424 if (end == space->top()) { | |
| 4425 start = end = space->limit(); | |
| 4426 } else { | |
| 4427 // At this point we are either at the start of a filler or we are at | |
| 4428 // the point where the space->top() used to be before the | |
| 4429 // visit_pointer_region call above. Either way we can skip the | |
| 4430 // object at the current spot: We don't promise to visit objects | |
| 4431 // allocated during heap traversal, and if space->top() moved then it | |
| 4432 // must be because an object was allocated at this point. | |
| 4433 start = end + HeapObject::FromAddress(end)->Size(); | |
| 4434 end = start; | |
| 4435 } | |
| 4436 } else { | |
| 4437 ASSERT(o != free_space_map); | |
| 4438 ASSERT(o != two_pointer_filler_map); | |
| 4439 ASSERT(end < space->top() || end >= space->limit()); | |
| 4440 end += kPointerSize; | |
| 4441 } | |
| 4442 } | |
| 4443 ASSERT(end == limit); | |
| 4444 if (start != end) { | |
| 4445 visit_pointer_region(start, end, copy_object_func); | |
| 4446 } | |
| 4447 } | 4449 } |
| 4448 } | 4450 } |
| 4449 | 4451 |
| 4450 | 4452 |
| 4453 void Heap::IteratePointersOnPage( | |
| 4454 PagedSpace* space, | |
| 4455 PointerRegionCallback visit_pointer_region, | |
| 4456 ObjectSlotCallback copy_object_func, | |
| 4457 Page* page) { | |
| 4458 Address visitable_start = page->ObjectAreaStart(); | |
| 4459 Address end_of_page = page->ObjectAreaEnd(); | |
| 4460 | |
| 4461 Address visitable_end = visitable_start; | |
| 4462 | |
| 4463 Object* free_space_map = Heap::free_space_map(); | |
| 4464 Object* two_pointer_filler_map = Heap::two_pointer_filler_map(); | |
| 4465 | |
| 4466 while (visitable_end < end_of_page) { | |
| 4467 Object* o = *reinterpret_cast<Object**>(visitable_end); | |
| 4468 // Skip fillers but not things that look like fillers in the special | |
| 4469 // garbage section which can contain anything. | |
| 4470 if (o == free_space_map || | |
| 4471 o == two_pointer_filler_map || | |
| 4472 visitable_end == space->top()) { | |
| 4473 if (visitable_start != visitable_end) { | |
| 4474 // After calling this the special garbage section may have moved. | |
| 4475 visit_pointer_region(visitable_start, visitable_end, copy_object_func); | |
| 4476 if (visitable_end >= space->top() && visitable_end < space->limit()) { | |
| 4477 visitable_end = space->limit(); | |
| 4478 visitable_start = visitable_end; | |
| 4479 continue; | |
| 4480 } | |
| 4481 } | |
| 4482 if (visitable_end == space->top() && visitable_end != space->limit()) { | |
| 4483 visitable_start = visitable_end = space->limit(); | |
| 4484 } else { | |
| 4485 // At this point we are either at the start of a filler or we are at | |
| 4486 // the point where the space->top() used to be before the | |
| 4487 // visit_pointer_region call above. Either way we can skip the | |
| 4488 // object at the current spot: We don't promise to visit objects | |
| 4489 // allocated during heap traversal, and if space->top() moved then it | |
| 4490 // must be because an object was allocated at this point. | |
| 4491 visitable_start = | |
| 4492 visitable_end + HeapObject::FromAddress(visitable_end)->Size(); | |
| 4493 visitable_end = visitable_start; | |
| 4494 } | |
| 4495 } else { | |
| 4496 ASSERT(o != free_space_map); | |
| 4497 ASSERT(o != two_pointer_filler_map); | |
| 4498 ASSERT(visitable_end < space->top() || visitable_end >= space->limit()); | |
| 4499 visitable_end += kPointerSize; | |
| 4500 } | |
| 4501 } | |
| 4502 ASSERT(visitable_end == end_of_page); | |
| 4503 if (visitable_start != visitable_end) { | |
| 4504 visit_pointer_region(visitable_start, visitable_end, copy_object_func); | |
| 4505 } | |
| 4506 } | |
| 4507 | |
| 4508 | |
| 4451 void Heap::IterateRoots(ObjectVisitor* v, VisitMode mode) { | 4509 void Heap::IterateRoots(ObjectVisitor* v, VisitMode mode) { |
| 4452 IterateStrongRoots(v, mode); | 4510 IterateStrongRoots(v, mode); |
| 4453 IterateWeakRoots(v, mode); | 4511 IterateWeakRoots(v, mode); |
| 4454 } | 4512 } |
| 4455 | 4513 |
| 4456 | 4514 |
| 4457 void Heap::IterateWeakRoots(ObjectVisitor* v, VisitMode mode) { | 4515 void Heap::IterateWeakRoots(ObjectVisitor* v, VisitMode mode) { |
| 4458 v->VisitPointer(reinterpret_cast<Object**>(&roots_[kSymbolTableRootIndex])); | 4516 v->VisitPointer(reinterpret_cast<Object**>(&roots_[kSymbolTableRootIndex])); |
| 4459 v->Synchronize("symbol_table"); | 4517 v->Synchronize("symbol_table"); |
| 4460 if (mode != VISIT_ALL_IN_SCAVENGE) { | 4518 if (mode != VISIT_ALL_IN_SCAVENGE) { |
| (...skipping 1139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5600 void ExternalStringTable::TearDown() { | 5658 void ExternalStringTable::TearDown() { |
| 5601 new_space_strings_.Free(); | 5659 new_space_strings_.Free(); |
| 5602 old_space_strings_.Free(); | 5660 old_space_strings_.Free(); |
| 5603 } | 5661 } |
| 5604 | 5662 |
| 5605 | 5663 |
| 5606 List<Object*> ExternalStringTable::new_space_strings_; | 5664 List<Object*> ExternalStringTable::new_space_strings_; |
| 5607 List<Object*> ExternalStringTable::old_space_strings_; | 5665 List<Object*> ExternalStringTable::old_space_strings_; |
| 5608 | 5666 |
| 5609 } } // namespace v8::internal | 5667 } } // namespace v8::internal |
| OLD | NEW |