Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 50 | 50 |
| 51 #define STRUCT_ALLOCATION(NAME, Name, name) Map* Heap::name##_map_; | 51 #define STRUCT_ALLOCATION(NAME, Name, name) Map* Heap::name##_map_; |
| 52 STRUCT_LIST(STRUCT_ALLOCATION) | 52 STRUCT_LIST(STRUCT_ALLOCATION) |
| 53 #undef STRUCT_ALLOCATION | 53 #undef STRUCT_ALLOCATION |
| 54 | 54 |
| 55 | 55 |
| 56 #define SYMBOL_ALLOCATION(name, string) String* Heap::name##_; | 56 #define SYMBOL_ALLOCATION(name, string) String* Heap::name##_; |
| 57 SYMBOL_LIST(SYMBOL_ALLOCATION) | 57 SYMBOL_LIST(SYMBOL_ALLOCATION) |
| 58 #undef SYMBOL_ALLOCATION | 58 #undef SYMBOL_ALLOCATION |
| 59 | 59 |
| 60 | 60 NewSpace Heap::new_space_; |
| 61 NewSpace* Heap::new_space_ = NULL; | |
| 62 OldSpace* Heap::old_pointer_space_ = NULL; | 61 OldSpace* Heap::old_pointer_space_ = NULL; |
| 63 OldSpace* Heap::old_data_space_ = NULL; | 62 OldSpace* Heap::old_data_space_ = NULL; |
| 64 OldSpace* Heap::code_space_ = NULL; | 63 OldSpace* Heap::code_space_ = NULL; |
| 65 MapSpace* Heap::map_space_ = NULL; | 64 MapSpace* Heap::map_space_ = NULL; |
| 66 LargeObjectSpace* Heap::lo_space_ = NULL; | 65 LargeObjectSpace* Heap::lo_space_ = NULL; |
| 67 | 66 |
| 68 int Heap::promoted_space_limit_ = 0; | 67 int Heap::promoted_space_limit_ = 0; |
| 69 int Heap::old_gen_exhausted_ = false; | 68 int Heap::old_gen_exhausted_ = false; |
| 70 | 69 |
| 71 int Heap::amount_of_external_allocated_memory_ = 0; | 70 int Heap::amount_of_external_allocated_memory_ = 0; |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 96 bool Heap::allocation_allowed_ = true; | 95 bool Heap::allocation_allowed_ = true; |
| 97 | 96 |
| 98 int Heap::allocation_timeout_ = 0; | 97 int Heap::allocation_timeout_ = 0; |
| 99 bool Heap::disallow_allocation_failure_ = false; | 98 bool Heap::disallow_allocation_failure_ = false; |
| 100 #endif // DEBUG | 99 #endif // DEBUG |
| 101 | 100 |
| 102 | 101 |
| 103 int Heap::Capacity() { | 102 int Heap::Capacity() { |
| 104 if (!HasBeenSetup()) return 0; | 103 if (!HasBeenSetup()) return 0; |
| 105 | 104 |
| 106 return new_space_->Capacity() + | 105 return new_space_.Capacity() + |
| 107 old_pointer_space_->Capacity() + | 106 old_pointer_space_->Capacity() + |
| 108 old_data_space_->Capacity() + | 107 old_data_space_->Capacity() + |
| 109 code_space_->Capacity() + | 108 code_space_->Capacity() + |
| 110 map_space_->Capacity(); | 109 map_space_->Capacity(); |
| 111 } | 110 } |
| 112 | 111 |
| 113 | 112 |
| 114 int Heap::Available() { | 113 int Heap::Available() { |
| 115 if (!HasBeenSetup()) return 0; | 114 if (!HasBeenSetup()) return 0; |
| 116 | 115 |
| 117 return new_space_->Available() + | 116 return new_space_.Available() + |
| 118 old_pointer_space_->Available() + | 117 old_pointer_space_->Available() + |
| 119 old_data_space_->Available() + | 118 old_data_space_->Available() + |
| 120 code_space_->Available() + | 119 code_space_->Available() + |
| 121 map_space_->Available(); | 120 map_space_->Available(); |
| 122 } | 121 } |
| 123 | 122 |
| 124 | 123 |
| 125 bool Heap::HasBeenSetup() { | 124 bool Heap::HasBeenSetup() { |
| 126 return new_space_ != NULL && | 125 return old_pointer_space_ != NULL && |
| 127 old_pointer_space_ != NULL && | |
| 128 old_data_space_ != NULL && | 126 old_data_space_ != NULL && |
| 129 code_space_ != NULL && | 127 code_space_ != NULL && |
| 130 map_space_ != NULL && | 128 map_space_ != NULL && |
| 131 lo_space_ != NULL; | 129 lo_space_ != NULL; |
| 132 } | 130 } |
| 133 | 131 |
| 134 | 132 |
| 135 GarbageCollector Heap::SelectGarbageCollector(AllocationSpace space) { | 133 GarbageCollector Heap::SelectGarbageCollector(AllocationSpace space) { |
| 136 // Is global GC requested? | 134 // Is global GC requested? |
| 137 if (space != NEW_SPACE || FLAG_gc_global) { | 135 if (space != NEW_SPACE || FLAG_gc_global) { |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 154 | 152 |
| 155 // Is there enough space left in OLD to guarantee that a scavenge can | 153 // Is there enough space left in OLD to guarantee that a scavenge can |
| 156 // succeed? | 154 // succeed? |
| 157 // | 155 // |
| 158 // Note that MemoryAllocator->MaxAvailable() undercounts the memory available | 156 // Note that MemoryAllocator->MaxAvailable() undercounts the memory available |
| 159 // for object promotion. It counts only the bytes that the memory | 157 // for object promotion. It counts only the bytes that the memory |
| 160 // allocator has not yet allocated from the OS and assigned to any space, | 158 // allocator has not yet allocated from the OS and assigned to any space, |
| 161 // and does not count available bytes already in the old space or code | 159 // and does not count available bytes already in the old space or code |
| 162 // space. Undercounting is safe---we may get an unrequested full GC when | 160 // space. Undercounting is safe---we may get an unrequested full GC when |
| 163 // a scavenge would have succeeded. | 161 // a scavenge would have succeeded. |
| 164 if (MemoryAllocator::MaxAvailable() <= new_space_->Size()) { | 162 if (MemoryAllocator::MaxAvailable() <= new_space_.Size()) { |
| 165 Counters::gc_compactor_caused_by_oldspace_exhaustion.Increment(); | 163 Counters::gc_compactor_caused_by_oldspace_exhaustion.Increment(); |
| 166 return MARK_COMPACTOR; | 164 return MARK_COMPACTOR; |
| 167 } | 165 } |
| 168 | 166 |
| 169 // Default | 167 // Default |
| 170 return SCAVENGER; | 168 return SCAVENGER; |
| 171 } | 169 } |
| 172 | 170 |
| 173 | 171 |
| 174 // TODO(1238405): Combine the infrastructure for --heap-stats and | 172 // TODO(1238405): Combine the infrastructure for --heap-stats and |
| 175 // --log-gc to avoid the complicated preprocessor and flag testing. | 173 // --log-gc to avoid the complicated preprocessor and flag testing. |
| 176 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) | 174 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) |
| 177 void Heap::ReportStatisticsBeforeGC() { | 175 void Heap::ReportStatisticsBeforeGC() { |
| 178 // Heap::ReportHeapStatistics will also log NewSpace statistics when | 176 // Heap::ReportHeapStatistics will also log NewSpace statistics when |
| 179 // compiled with ENABLE_LOGGING_AND_PROFILING and --log-gc is set. The | 177 // compiled with ENABLE_LOGGING_AND_PROFILING and --log-gc is set. The |
| 180 // following logic is used to avoid double logging. | 178 // following logic is used to avoid double logging. |
| 181 #if defined(DEBUG) && defined(ENABLE_LOGGING_AND_PROFILING) | 179 #if defined(DEBUG) && defined(ENABLE_LOGGING_AND_PROFILING) |
| 182 if (FLAG_heap_stats || FLAG_log_gc) new_space_->CollectStatistics(); | 180 if (FLAG_heap_stats || FLAG_log_gc) new_space_.CollectStatistics(); |
| 183 if (FLAG_heap_stats) { | 181 if (FLAG_heap_stats) { |
| 184 ReportHeapStatistics("Before GC"); | 182 ReportHeapStatistics("Before GC"); |
| 185 } else if (FLAG_log_gc) { | 183 } else if (FLAG_log_gc) { |
| 186 new_space_->ReportStatistics(); | 184 new_space_.ReportStatistics(); |
| 187 } | 185 } |
| 188 if (FLAG_heap_stats || FLAG_log_gc) new_space_->ClearHistograms(); | 186 if (FLAG_heap_stats || FLAG_log_gc) new_space_.ClearHistograms(); |
| 189 #elif defined(DEBUG) | 187 #elif defined(DEBUG) |
| 190 if (FLAG_heap_stats) { | 188 if (FLAG_heap_stats) { |
| 191 new_space_->CollectStatistics(); | 189 new_space_.CollectStatistics(); |
| 192 ReportHeapStatistics("Before GC"); | 190 ReportHeapStatistics("Before GC"); |
| 193 new_space_->ClearHistograms(); | 191 new_space_.ClearHistograms(); |
| 194 } | 192 } |
| 195 #elif defined(ENABLE_LOGGING_AND_PROFILING) | 193 #elif defined(ENABLE_LOGGING_AND_PROFILING) |
| 196 if (FLAG_log_gc) { | 194 if (FLAG_log_gc) { |
| 197 new_space_->CollectStatistics(); | 195 new_space_.CollectStatistics(); |
| 198 new_space_->ReportStatistics(); | 196 new_space_.ReportStatistics(); |
| 199 new_space_->ClearHistograms(); | 197 new_space_.ClearHistograms(); |
| 200 } | 198 } |
| 201 #endif | 199 #endif |
| 202 } | 200 } |
| 203 | 201 |
| 204 | 202 |
| 205 // TODO(1238405): Combine the infrastructure for --heap-stats and | 203 // TODO(1238405): Combine the infrastructure for --heap-stats and |
| 206 // --log-gc to avoid the complicated preprocessor and flag testing. | 204 // --log-gc to avoid the complicated preprocessor and flag testing. |
| 207 void Heap::ReportStatisticsAfterGC() { | 205 void Heap::ReportStatisticsAfterGC() { |
| 208 // Similar to the before GC, we use some complicated logic to ensure that | 206 // Similar to the before GC, we use some complicated logic to ensure that |
| 209 // NewSpace statistics are logged exactly once when --log-gc is turned on. | 207 // NewSpace statistics are logged exactly once when --log-gc is turned on. |
| 210 #if defined(DEBUG) && defined(ENABLE_LOGGING_AND_PROFILING) | 208 #if defined(DEBUG) && defined(ENABLE_LOGGING_AND_PROFILING) |
| 211 if (FLAG_heap_stats) { | 209 if (FLAG_heap_stats) { |
| 212 ReportHeapStatistics("After GC"); | 210 ReportHeapStatistics("After GC"); |
| 213 } else if (FLAG_log_gc) { | 211 } else if (FLAG_log_gc) { |
| 214 new_space_->ReportStatistics(); | 212 new_space_.ReportStatistics(); |
| 215 } | 213 } |
| 216 #elif defined(DEBUG) | 214 #elif defined(DEBUG) |
| 217 if (FLAG_heap_stats) ReportHeapStatistics("After GC"); | 215 if (FLAG_heap_stats) ReportHeapStatistics("After GC"); |
| 218 #elif defined(ENABLE_LOGGING_AND_PROFILING) | 216 #elif defined(ENABLE_LOGGING_AND_PROFILING) |
| 219 if (FLAG_log_gc) new_space_->ReportStatistics(); | 217 if (FLAG_log_gc) new_space_.ReportStatistics(); |
| 220 #endif | 218 #endif |
| 221 } | 219 } |
| 222 #endif // defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) | 220 #endif // defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) |
| 223 | 221 |
| 224 | 222 |
| 225 void Heap::GarbageCollectionPrologue() { | 223 void Heap::GarbageCollectionPrologue() { |
| 226 RegExpImpl::NewSpaceCollectionPrologue(); | 224 RegExpImpl::NewSpaceCollectionPrologue(); |
| 227 gc_count_++; | 225 gc_count_++; |
| 228 #ifdef DEBUG | 226 #ifdef DEBUG |
| 229 ASSERT(allocation_allowed_ && gc_state_ == NOT_IN_GC); | 227 ASSERT(allocation_allowed_ && gc_state_ == NOT_IN_GC); |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 322 GarbageCollectionEpilogue(); | 320 GarbageCollectionEpilogue(); |
| 323 } | 321 } |
| 324 | 322 |
| 325 | 323 |
| 326 #ifdef ENABLE_LOGGING_AND_PROFILING | 324 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 327 if (FLAG_log_gc) HeapProfiler::WriteSample(); | 325 if (FLAG_log_gc) HeapProfiler::WriteSample(); |
| 328 #endif | 326 #endif |
| 329 | 327 |
| 330 switch (space) { | 328 switch (space) { |
| 331 case NEW_SPACE: | 329 case NEW_SPACE: |
| 332 return new_space_->Available() >= requested_size; | 330 return new_space_.Available() >= requested_size; |
| 333 case OLD_POINTER_SPACE: | 331 case OLD_POINTER_SPACE: |
| 334 return old_pointer_space_->Available() >= requested_size; | 332 return old_pointer_space_->Available() >= requested_size; |
| 335 case OLD_DATA_SPACE: | 333 case OLD_DATA_SPACE: |
| 336 return old_data_space_->Available() >= requested_size; | 334 return old_data_space_->Available() >= requested_size; |
| 337 case CODE_SPACE: | 335 case CODE_SPACE: |
| 338 return code_space_->Available() >= requested_size; | 336 return code_space_->Available() >= requested_size; |
| 339 case MAP_SPACE: | 337 case MAP_SPACE: |
| 340 return map_space_->Available() >= requested_size; | 338 return map_space_->Available() >= requested_size; |
| 341 case LO_SPACE: | 339 case LO_SPACE: |
| 342 return lo_space_->Available() >= requested_size; | 340 return lo_space_->Available() >= requested_size; |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 454 CopyObject(p); | 452 CopyObject(p); |
| 455 } | 453 } |
| 456 | 454 |
| 457 void VisitPointers(Object** start, Object** end) { | 455 void VisitPointers(Object** start, Object** end) { |
| 458 // Copy all HeapObject pointers in [start, end) | 456 // Copy all HeapObject pointers in [start, end) |
| 459 for (Object** p = start; p < end; p++) CopyObject(p); | 457 for (Object** p = start; p < end; p++) CopyObject(p); |
| 460 } | 458 } |
| 461 | 459 |
| 462 private: | 460 private: |
| 463 void CopyObject(Object** p) { | 461 void CopyObject(Object** p) { |
| 464 if (!Heap::InFromSpace(*p)) return; | 462 if (!Heap::InNewSpace(*p)) return; |
| 465 Heap::CopyObject(reinterpret_cast<HeapObject**>(p)); | 463 Heap::CopyObject(reinterpret_cast<HeapObject**>(p)); |
| 466 } | 464 } |
| 467 }; | 465 }; |
| 468 | 466 |
| 469 | 467 |
| 470 // Shared state read by the scavenge collector and set by CopyObject. | 468 // Shared state read by the scavenge collector and set by CopyObject. |
| 471 static Address promoted_top = NULL; | 469 static Address promoted_top = NULL; |
| 472 | 470 |
| 473 | 471 |
| 474 #ifdef DEBUG | 472 #ifdef DEBUG |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 503 } | 501 } |
| 504 } | 502 } |
| 505 #endif | 503 #endif |
| 506 | 504 |
| 507 gc_state_ = SCAVENGE; | 505 gc_state_ = SCAVENGE; |
| 508 | 506 |
| 509 // Implements Cheney's copying algorithm | 507 // Implements Cheney's copying algorithm |
| 510 LOG(ResourceEvent("scavenge", "begin")); | 508 LOG(ResourceEvent("scavenge", "begin")); |
| 511 | 509 |
| 512 scavenge_count_++; | 510 scavenge_count_++; |
| 513 if (new_space_->Capacity() < new_space_->MaximumCapacity() && | 511 if (new_space_.Capacity() < new_space_.MaximumCapacity() && |
| 514 scavenge_count_ > new_space_growth_limit_) { | 512 scavenge_count_ > new_space_growth_limit_) { |
| 515 // Double the size of the new space, and double the limit. The next | 513 // Double the size of the new space, and double the limit. The next |
| 516 // doubling attempt will occur after the current new_space_growth_limit_ | 514 // doubling attempt will occur after the current new_space_growth_limit_ |
| 517 // more collections. | 515 // more collections. |
| 518 // TODO(1240712): NewSpace::Double has a return value which is | 516 // TODO(1240712): NewSpace::Double has a return value which is |
| 519 // ignored here. | 517 // ignored here. |
| 520 new_space_->Double(); | 518 new_space_.Double(); |
| 521 new_space_growth_limit_ *= 2; | 519 new_space_growth_limit_ *= 2; |
| 522 } | 520 } |
| 523 | 521 |
| 524 // Flip the semispaces. After flipping, to space is empty, from space has | 522 // Flip the semispaces. After flipping, to space is empty, from space has |
| 525 // live objects. | 523 // live objects. |
| 526 new_space_->Flip(); | 524 new_space_.Flip(); |
| 527 new_space_->ResetAllocationInfo(); | 525 new_space_.ResetAllocationInfo(); |
| 528 | 526 |
| 529 // We need to sweep newly copied objects which can be in either the to space | 527 // We need to sweep newly copied objects which can be in either the to space |
| 530 // or the old space. For to space objects, we use a mark. Newly copied | 528 // or the old space. For to space objects, we use a mark. Newly copied |
| 531 // objects lie between the mark and the allocation top. For objects | 529 // objects lie between the mark and the allocation top. For objects |
| 532 // promoted to old space, we write their addresses downward from the top of | 530 // promoted to old space, we write their addresses downward from the top of |
| 533 // the new space. Sweeping newly promoted objects requires an allocation | 531 // the new space. Sweeping newly promoted objects requires an allocation |
| 534 // pointer and a mark. Note that the allocation pointer 'top' actually | 532 // pointer and a mark. Note that the allocation pointer 'top' actually |
| 535 // moves downward from the high address in the to space. | 533 // moves downward from the high address in the to space. |
| 536 // | 534 // |
| 537 // There is guaranteed to be enough room at the top of the to space for the | 535 // There is guaranteed to be enough room at the top of the to space for the |
| 538 // addresses of promoted objects: every object promoted frees up its size in | 536 // addresses of promoted objects: every object promoted frees up its size in |
| 539 // bytes from the top of the new space, and objects are at least one pointer | 537 // bytes from the top of the new space, and objects are at least one pointer |
| 540 // in size. Using the new space to record promoted addresses makes the | 538 // in size. Using the new space to record promoted addresses makes the |
| 541 // scavenge collector agnostic to the allocation strategy (eg, linear or | 539 // scavenge collector agnostic to the allocation strategy (eg, linear or |
| 542 // free-list) used in old space. | 540 // free-list) used in old space. |
| 543 Address new_mark = new_space_->ToSpaceLow(); | 541 Address new_mark = new_space_.ToSpaceLow(); |
| 544 Address promoted_mark = new_space_->ToSpaceHigh(); | 542 Address promoted_mark = new_space_.ToSpaceHigh(); |
| 545 promoted_top = new_space_->ToSpaceHigh(); | 543 promoted_top = new_space_.ToSpaceHigh(); |
| 546 | 544 |
| 547 CopyVisitor copy_visitor; | 545 CopyVisitor copy_visitor; |
| 548 // Copy roots. | 546 // Copy roots. |
| 549 IterateRoots(©_visitor); | 547 IterateRoots(©_visitor); |
| 550 | 548 |
| 551 // Copy objects reachable from the old generation. By definition, there | 549 // Copy objects reachable from the old generation. By definition, there |
| 552 // are no intergenerational pointers in code or data spaces. | 550 // are no intergenerational pointers in code or data spaces. |
| 553 IterateRSet(old_pointer_space_, &CopyObject); | 551 IterateRSet(old_pointer_space_, &CopyObject); |
| 554 IterateRSet(map_space_, &CopyObject); | 552 IterateRSet(map_space_, &CopyObject); |
| 555 lo_space_->IterateRSet(&CopyObject); | 553 lo_space_->IterateRSet(&CopyObject); |
| 556 | 554 |
| 557 bool has_processed_weak_pointers = false; | 555 bool has_processed_weak_pointers = false; |
| 558 | 556 |
| 559 while (true) { | 557 while (true) { |
| 560 ASSERT(new_mark <= new_space_->top()); | 558 ASSERT(new_mark <= new_space_.top()); |
| 561 ASSERT(promoted_mark >= promoted_top); | 559 ASSERT(promoted_mark >= promoted_top); |
| 562 | 560 |
| 563 // Copy objects reachable from newly copied objects. | 561 // Copy objects reachable from newly copied objects. |
| 564 while (new_mark < new_space_->top() || promoted_mark > promoted_top) { | 562 while (new_mark < new_space_.top() || promoted_mark > promoted_top) { |
| 565 // Sweep newly copied objects in the to space. The allocation pointer | 563 // Sweep newly copied objects in the to space. The allocation pointer |
| 566 // can change during sweeping. | 564 // can change during sweeping. |
| 567 Address previous_top = new_space_->top(); | 565 Address previous_top = new_space_.top(); |
| 568 SemiSpaceIterator new_it(new_space_, new_mark); | 566 SemiSpaceIterator new_it(new_space(), new_mark); |
| 569 while (new_it.has_next()) { | 567 while (new_it.has_next()) { |
| 570 new_it.next()->Iterate(©_visitor); | 568 new_it.next()->Iterate(©_visitor); |
| 571 } | 569 } |
| 572 new_mark = previous_top; | 570 new_mark = previous_top; |
| 573 | 571 |
| 574 // Sweep newly copied objects in the old space. The promotion 'top' | 572 // Sweep newly copied objects in the old space. The promotion 'top' |
| 575 // pointer could change during sweeping. | 573 // pointer could change during sweeping. |
| 576 previous_top = promoted_top; | 574 previous_top = promoted_top; |
| 577 for (Address current = promoted_mark - kPointerSize; | 575 for (Address current = promoted_mark - kPointerSize; |
| 578 current >= previous_top; | 576 current >= previous_top; |
| 579 current -= kPointerSize) { | 577 current -= kPointerSize) { |
| 580 HeapObject* object = HeapObject::cast(Memory::Object_at(current)); | 578 HeapObject* object = HeapObject::cast(Memory::Object_at(current)); |
| 581 object->Iterate(©_visitor); | 579 object->Iterate(©_visitor); |
| 582 UpdateRSet(object); | 580 UpdateRSet(object); |
| 583 } | 581 } |
| 584 promoted_mark = previous_top; | 582 promoted_mark = previous_top; |
| 585 } | 583 } |
| 586 | 584 |
| 587 if (has_processed_weak_pointers) break; // We are done. | 585 if (has_processed_weak_pointers) break; // We are done. |
| 588 // Copy objects reachable from weak pointers. | 586 // Copy objects reachable from weak pointers. |
| 589 GlobalHandles::IterateWeakRoots(©_visitor); | 587 GlobalHandles::IterateWeakRoots(©_visitor); |
| 590 has_processed_weak_pointers = true; | 588 has_processed_weak_pointers = true; |
| 591 } | 589 } |
| 592 | 590 |
| 593 // Set age mark. | 591 // Set age mark. |
| 594 new_space_->set_age_mark(new_mark); | 592 new_space_.set_age_mark(new_mark); |
| 595 | 593 |
| 596 LOG(ResourceEvent("scavenge", "end")); | 594 LOG(ResourceEvent("scavenge", "end")); |
| 597 | 595 |
| 598 gc_state_ = NOT_IN_GC; | 596 gc_state_ = NOT_IN_GC; |
| 599 } | 597 } |
| 600 | 598 |
| 601 | 599 |
| 602 void Heap::ClearRSetRange(Address start, int size_in_bytes) { | 600 void Heap::ClearRSetRange(Address start, int size_in_bytes) { |
| 603 uint32_t start_bit; | 601 uint32_t start_bit; |
| 604 Address start_word_address = | 602 Address start_word_address = |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 711 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) | 709 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) |
| 712 void Heap::RecordCopiedObject(HeapObject* obj) { | 710 void Heap::RecordCopiedObject(HeapObject* obj) { |
| 713 bool should_record = false; | 711 bool should_record = false; |
| 714 #ifdef DEBUG | 712 #ifdef DEBUG |
| 715 should_record = FLAG_heap_stats; | 713 should_record = FLAG_heap_stats; |
| 716 #endif | 714 #endif |
| 717 #ifdef ENABLE_LOGGING_AND_PROFILING | 715 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 718 should_record = should_record || FLAG_log_gc; | 716 should_record = should_record || FLAG_log_gc; |
| 719 #endif | 717 #endif |
| 720 if (should_record) { | 718 if (should_record) { |
| 721 if (new_space_->Contains(obj)) { | 719 if (new_space_.Contains(obj)) { |
| 722 new_space_->RecordAllocation(obj); | 720 new_space_.RecordAllocation(obj); |
| 723 } else { | 721 } else { |
| 724 new_space_->RecordPromotion(obj); | 722 new_space_.RecordPromotion(obj); |
| 725 } | 723 } |
| 726 } | 724 } |
| 727 } | 725 } |
| 728 #endif // defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) | 726 #endif // defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) |
| 729 | 727 |
| 730 | 728 |
| 731 HeapObject* Heap::MigrateObject(HeapObject** source_p, | 729 HeapObject* Heap::MigrateObject(HeapObject* source, |
| 732 HeapObject* target, | 730 HeapObject* target, |
| 733 int size) { | 731 int size) { |
| 734 void** src = reinterpret_cast<void**>((*source_p)->address()); | 732 void** src = reinterpret_cast<void**>(source->address()); |
| 735 void** dst = reinterpret_cast<void**>(target->address()); | 733 void** dst = reinterpret_cast<void**>(target->address()); |
| 736 | 734 |
| 737 // Use block copying memcpy if the object we're migrating is big | 735 // Use block copying memcpy if the object we're migrating is big |
| 738 // enough to justify the extra call/setup overhead. | 736 // enough to justify the extra call/setup overhead. |
| 739 static const int kBlockCopyLimit = 16 * kPointerSize; | 737 static const int kBlockCopyLimit = 16 * kPointerSize; |
| 740 | 738 |
| 741 if (size >= kBlockCopyLimit) { | 739 if (size >= kBlockCopyLimit) { |
| 742 memcpy(dst, src, size); | 740 memcpy(dst, src, size); |
| 743 } else { | 741 } else { |
| 744 int remaining = size / kPointerSize; | 742 int remaining = size / kPointerSize; |
| 745 do { | 743 do { |
| 746 remaining--; | 744 remaining--; |
| 747 *dst++ = *src++; | 745 *dst++ = *src++; |
| 748 } while (remaining > 0); | 746 } while (remaining > 0); |
| 749 } | 747 } |
| 750 | 748 |
| 751 // Set the forwarding address. | 749 // Set the forwarding address. |
| 752 (*source_p)->set_map_word(MapWord::FromForwardingAddress(target)); | 750 source->set_map_word(MapWord::FromForwardingAddress(target)); |
| 753 | 751 |
| 754 // Update NewSpace stats if necessary. | 752 // Update NewSpace stats if necessary. |
| 755 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) | 753 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) |
| 756 RecordCopiedObject(target); | 754 RecordCopiedObject(target); |
| 757 #endif | 755 #endif |
| 758 | 756 |
| 759 return target; | 757 return target; |
| 760 } | 758 } |
| 761 | 759 |
| 762 | 760 |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 782 // Heap::empty_string(). We do not use object->IsConsString because we | 780 // Heap::empty_string(). We do not use object->IsConsString because we |
| 783 // already know that object has the heap object tag. | 781 // already know that object has the heap object tag. |
| 784 InstanceType type = first_word.ToMap()->instance_type(); | 782 InstanceType type = first_word.ToMap()->instance_type(); |
| 785 if (type < FIRST_NONSTRING_TYPE && | 783 if (type < FIRST_NONSTRING_TYPE && |
| 786 String::cast(object)->representation_tag() == kConsStringTag && | 784 String::cast(object)->representation_tag() == kConsStringTag && |
| 787 ConsString::cast(object)->second() == Heap::empty_string()) { | 785 ConsString::cast(object)->second() == Heap::empty_string()) { |
| 788 object = HeapObject::cast(ConsString::cast(object)->first()); | 786 object = HeapObject::cast(ConsString::cast(object)->first()); |
| 789 *p = object; | 787 *p = object; |
| 790 // After patching *p we have to repeat the checks that object is in the | 788 // After patching *p we have to repeat the checks that object is in the |
| 791 // active semispace of the young generation and not already copied. | 789 // active semispace of the young generation and not already copied. |
| 792 if (!InFromSpace(object)) return; | 790 if (!InNewSpace(object)) return; |
| 793 first_word = object->map_word(); | 791 first_word = object->map_word(); |
| 794 if (first_word.IsForwardingAddress()) { | 792 if (first_word.IsForwardingAddress()) { |
| 795 *p = first_word.ToForwardingAddress(); | 793 *p = first_word.ToForwardingAddress(); |
| 796 return; | 794 return; |
| 797 } | 795 } |
| 798 type = first_word.ToMap()->instance_type(); | 796 type = first_word.ToMap()->instance_type(); |
| 799 } | 797 } |
| 800 | 798 |
| 801 int object_size = object->SizeFromMap(first_word.ToMap()); | 799 int object_size = object->SizeFromMap(first_word.ToMap()); |
| 802 Object* result; | 800 Object* result; |
| 803 // If the object should be promoted, we try to copy it to old space. | 801 // If the object should be promoted, we try to copy it to old space. |
| 804 if (ShouldBePromoted(object->address(), object_size)) { | 802 if (ShouldBePromoted(object->address(), object_size)) { |
| 805 OldSpace* target_space = Heap::TargetSpace(object); | 803 OldSpace* target_space = Heap::TargetSpace(object); |
| 806 ASSERT(target_space == Heap::old_pointer_space_ || | 804 ASSERT(target_space == Heap::old_pointer_space_ || |
| 807 target_space == Heap::old_data_space_); | 805 target_space == Heap::old_data_space_); |
| 808 result = target_space->AllocateRaw(object_size); | 806 result = target_space->AllocateRaw(object_size); |
| 809 | 807 |
| 810 if (!result->IsFailure()) { | 808 if (!result->IsFailure()) { |
| 811 *p = MigrateObject(p, HeapObject::cast(result), object_size); | 809 *p = MigrateObject(object, HeapObject::cast(result), object_size); |
| 812 if (target_space == Heap::old_pointer_space_) { | 810 if (target_space == Heap::old_pointer_space_) { |
| 813 // Record the object's address at the top of the to space, to allow | 811 // Record the object's address at the top of the to space, to allow |
| 814 // it to be swept by the scavenger. | 812 // it to be swept by the scavenger. |
| 815 promoted_top -= kPointerSize; | 813 promoted_top -= kPointerSize; |
| 816 Memory::Object_at(promoted_top) = *p; | 814 Memory::Object_at(promoted_top) = *p; |
| 817 } else { | 815 } else { |
| 818 #ifdef DEBUG | 816 #ifdef DEBUG |
| 819 // Objects promoted to the data space should not have pointers to | 817 // Objects promoted to the data space should not have pointers to |
| 820 // new space. | 818 // new space. |
| 821 VerifyNonPointerSpacePointersVisitor v; | 819 VerifyNonPointerSpacePointersVisitor v; |
| 822 (*p)->Iterate(&v); | 820 (*p)->Iterate(&v); |
| 823 #endif | 821 #endif |
| 824 } | 822 } |
| 825 return; | 823 return; |
| 826 } | 824 } |
| 827 } | 825 } |
| 828 | 826 |
| 829 // The object should remain in new space or the old space allocation failed. | 827 // The object should remain in new space or the old space allocation failed. |
| 830 result = new_space_->AllocateRaw(object_size); | 828 result = new_space_.AllocateRaw(object_size); |
| 831 // Failed allocation at this point is utterly unexpected. | 829 // Failed allocation at this point is utterly unexpected. |
| 832 ASSERT(!result->IsFailure()); | 830 ASSERT(!result->IsFailure()); |
| 833 *p = MigrateObject(p, HeapObject::cast(result), object_size); | 831 *p = MigrateObject(object, HeapObject::cast(result), object_size); |
| 834 } | 832 } |
| 835 | 833 |
| 836 | 834 |
| 837 Object* Heap::AllocatePartialMap(InstanceType instance_type, | 835 Object* Heap::AllocatePartialMap(InstanceType instance_type, |
| 838 int instance_size) { | 836 int instance_size) { |
| 839 Object* result = AllocateRawMap(Map::kSize); | 837 Object* result = AllocateRawMap(Map::kSize); |
| 840 if (result->IsFailure()) return result; | 838 if (result->IsFailure()) return result; |
| 841 | 839 |
| 842 // Map::cast cannot be used due to uninitialized map field. | 840 // Map::cast cannot be used due to uninitialized map field. |
| 843 reinterpret_cast<Map*>(result)->set_map(meta_map()); | 841 reinterpret_cast<Map*>(result)->set_map(meta_map()); |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1023 HeapNumber::cast(result)->set_value(value); | 1021 HeapNumber::cast(result)->set_value(value); |
| 1024 return result; | 1022 return result; |
| 1025 } | 1023 } |
| 1026 | 1024 |
| 1027 | 1025 |
| 1028 Object* Heap::AllocateHeapNumber(double value) { | 1026 Object* Heap::AllocateHeapNumber(double value) { |
| 1029 // This version of AllocateHeapNumber is optimized for | 1027 // This version of AllocateHeapNumber is optimized for |
| 1030 // allocation in new space. | 1028 // allocation in new space. |
| 1031 STATIC_ASSERT(HeapNumber::kSize <= Page::kMaxHeapObjectSize); | 1029 STATIC_ASSERT(HeapNumber::kSize <= Page::kMaxHeapObjectSize); |
| 1032 ASSERT(allocation_allowed_ && gc_state_ == NOT_IN_GC); | 1030 ASSERT(allocation_allowed_ && gc_state_ == NOT_IN_GC); |
| 1033 Object* result = new_space_->AllocateRaw(HeapNumber::kSize); | 1031 Object* result = new_space_.AllocateRaw(HeapNumber::kSize); |
| 1034 if (result->IsFailure()) return result; | 1032 if (result->IsFailure()) return result; |
| 1035 HeapObject::cast(result)->set_map(heap_number_map()); | 1033 HeapObject::cast(result)->set_map(heap_number_map()); |
| 1036 HeapNumber::cast(result)->set_value(value); | 1034 HeapNumber::cast(result)->set_value(value); |
| 1037 return result; | 1035 return result; |
| 1038 } | 1036 } |
| 1039 | 1037 |
| 1040 | 1038 |
| 1041 Object* Heap::CreateOddball(Map* map, | 1039 Object* Heap::CreateOddball(Map* map, |
| 1042 const char* to_string, | 1040 const char* to_string, |
| 1043 Object* to_number) { | 1041 Object* to_number) { |
| (...skipping 1140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2184 PrintF("promoted_space_limit_ %d\n", promoted_space_limit_); | 2182 PrintF("promoted_space_limit_ %d\n", promoted_space_limit_); |
| 2185 | 2183 |
| 2186 PrintF("\n"); | 2184 PrintF("\n"); |
| 2187 PrintF("Number of handles : %d\n", HandleScope::NumberOfHandles()); | 2185 PrintF("Number of handles : %d\n", HandleScope::NumberOfHandles()); |
| 2188 GlobalHandles::PrintStats(); | 2186 GlobalHandles::PrintStats(); |
| 2189 PrintF("\n"); | 2187 PrintF("\n"); |
| 2190 | 2188 |
| 2191 PrintF("Heap statistics : "); | 2189 PrintF("Heap statistics : "); |
| 2192 MemoryAllocator::ReportStatistics(); | 2190 MemoryAllocator::ReportStatistics(); |
| 2193 PrintF("To space : "); | 2191 PrintF("To space : "); |
| 2194 new_space_->ReportStatistics(); | 2192 new_space_.ReportStatistics(); |
| 2195 PrintF("Old pointer space : "); | 2193 PrintF("Old pointer space : "); |
| 2196 old_pointer_space_->ReportStatistics(); | 2194 old_pointer_space_->ReportStatistics(); |
| 2197 PrintF("Old data space : "); | 2195 PrintF("Old data space : "); |
| 2198 old_data_space_->ReportStatistics(); | 2196 old_data_space_->ReportStatistics(); |
| 2199 PrintF("Code space : "); | 2197 PrintF("Code space : "); |
| 2200 code_space_->ReportStatistics(); | 2198 code_space_->ReportStatistics(); |
| 2201 PrintF("Map space : "); | 2199 PrintF("Map space : "); |
| 2202 map_space_->ReportStatistics(); | 2200 map_space_->ReportStatistics(); |
| 2203 PrintF("Large object space : "); | 2201 PrintF("Large object space : "); |
| 2204 lo_space_->ReportStatistics(); | 2202 lo_space_->ReportStatistics(); |
| 2205 PrintF(">>>>>> ========================================= >>>>>>\n"); | 2203 PrintF(">>>>>> ========================================= >>>>>>\n"); |
| 2206 } | 2204 } |
| 2207 | 2205 |
| 2208 #endif // DEBUG | 2206 #endif // DEBUG |
| 2209 | 2207 |
| 2210 bool Heap::Contains(HeapObject* value) { | 2208 bool Heap::Contains(HeapObject* value) { |
| 2211 return Contains(value->address()); | 2209 return Contains(value->address()); |
| 2212 } | 2210 } |
| 2213 | 2211 |
| 2214 | 2212 |
| 2215 bool Heap::Contains(Address addr) { | 2213 bool Heap::Contains(Address addr) { |
| 2216 if (OS::IsOutsideAllocatedSpace(addr)) return false; | 2214 if (OS::IsOutsideAllocatedSpace(addr)) return false; |
| 2217 return HasBeenSetup() && | 2215 return HasBeenSetup() && |
| 2218 (new_space_->ToSpaceContains(addr) || | 2216 (new_space_.ToSpaceContains(addr) || |
| 2219 old_pointer_space_->Contains(addr) || | 2217 old_pointer_space_->Contains(addr) || |
| 2220 old_data_space_->Contains(addr) || | 2218 old_data_space_->Contains(addr) || |
| 2221 code_space_->Contains(addr) || | 2219 code_space_->Contains(addr) || |
| 2222 map_space_->Contains(addr) || | 2220 map_space_->Contains(addr) || |
| 2223 lo_space_->SlowContains(addr)); | 2221 lo_space_->SlowContains(addr)); |
| 2224 } | 2222 } |
| 2225 | 2223 |
| 2226 | 2224 |
| 2227 bool Heap::InSpace(HeapObject* value, AllocationSpace space) { | 2225 bool Heap::InSpace(HeapObject* value, AllocationSpace space) { |
| 2228 return InSpace(value->address(), space); | 2226 return InSpace(value->address(), space); |
| 2229 } | 2227 } |
| 2230 | 2228 |
| 2231 | 2229 |
| 2232 bool Heap::InSpace(Address addr, AllocationSpace space) { | 2230 bool Heap::InSpace(Address addr, AllocationSpace space) { |
| 2233 if (OS::IsOutsideAllocatedSpace(addr)) return false; | 2231 if (OS::IsOutsideAllocatedSpace(addr)) return false; |
| 2234 if (!HasBeenSetup()) return false; | 2232 if (!HasBeenSetup()) return false; |
| 2235 | 2233 |
| 2236 switch (space) { | 2234 switch (space) { |
| 2237 case NEW_SPACE: | 2235 case NEW_SPACE: |
| 2238 return new_space_->ToSpaceContains(addr); | 2236 return new_space_.ToSpaceContains(addr); |
| 2239 case OLD_POINTER_SPACE: | 2237 case OLD_POINTER_SPACE: |
| 2240 return old_pointer_space_->Contains(addr); | 2238 return old_pointer_space_->Contains(addr); |
| 2241 case OLD_DATA_SPACE: | 2239 case OLD_DATA_SPACE: |
| 2242 return old_data_space_->Contains(addr); | 2240 return old_data_space_->Contains(addr); |
| 2243 case CODE_SPACE: | 2241 case CODE_SPACE: |
| 2244 return code_space_->Contains(addr); | 2242 return code_space_->Contains(addr); |
| 2245 case MAP_SPACE: | 2243 case MAP_SPACE: |
| 2246 return map_space_->Contains(addr); | 2244 return map_space_->Contains(addr); |
| 2247 case LO_SPACE: | 2245 case LO_SPACE: |
| 2248 return lo_space_->SlowContains(addr); | 2246 return lo_space_->SlowContains(addr); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2296 return true; | 2294 return true; |
| 2297 } | 2295 } |
| 2298 SymbolTable* table = SymbolTable::cast(symbol_table_); | 2296 SymbolTable* table = SymbolTable::cast(symbol_table_); |
| 2299 return table->LookupSymbolIfExists(string, symbol); | 2297 return table->LookupSymbolIfExists(string, symbol); |
| 2300 } | 2298 } |
| 2301 | 2299 |
| 2302 | 2300 |
| 2303 #ifdef DEBUG | 2301 #ifdef DEBUG |
| 2304 void Heap::ZapFromSpace() { | 2302 void Heap::ZapFromSpace() { |
| 2305 ASSERT(HAS_HEAP_OBJECT_TAG(kFromSpaceZapValue)); | 2303 ASSERT(HAS_HEAP_OBJECT_TAG(kFromSpaceZapValue)); |
| 2306 for (Address a = new_space_->FromSpaceLow(); | 2304 for (Address a = new_space_.FromSpaceLow(); |
| 2307 a < new_space_->FromSpaceHigh(); | 2305 a < new_space_.FromSpaceHigh(); |
| 2308 a += kPointerSize) { | 2306 a += kPointerSize) { |
| 2309 Memory::Address_at(a) = kFromSpaceZapValue; | 2307 Memory::Address_at(a) = kFromSpaceZapValue; |
| 2310 } | 2308 } |
| 2311 } | 2309 } |
| 2312 #endif // DEBUG | 2310 #endif // DEBUG |
| 2313 | 2311 |
| 2314 | 2312 |
| 2315 void Heap::IterateRSetRange(Address object_start, | 2313 void Heap::IterateRSetRange(Address object_start, |
| 2316 Address object_end, | 2314 Address object_end, |
| 2317 Address rset_start, | 2315 Address rset_start, |
| 2318 ObjectSlotCallback copy_object_func) { | 2316 ObjectSlotCallback copy_object_func) { |
| 2319 Address object_address = object_start; | 2317 Address object_address = object_start; |
| 2320 Address rset_address = rset_start; | 2318 Address rset_address = rset_start; |
| 2321 | 2319 |
| 2322 // Loop over all the pointers in [object_start, object_end). | 2320 // Loop over all the pointers in [object_start, object_end). |
| 2323 while (object_address < object_end) { | 2321 while (object_address < object_end) { |
| 2324 uint32_t rset_word = Memory::uint32_at(rset_address); | 2322 uint32_t rset_word = Memory::uint32_at(rset_address); |
| 2325 | |
| 2326 if (rset_word != 0) { | 2323 if (rset_word != 0) { |
| 2327 // Bits were set. | |
| 2328 uint32_t result_rset = rset_word; | 2324 uint32_t result_rset = rset_word; |
| 2329 | 2325 for(uint32_t bitmask = 1; bitmask != 0; bitmask = bitmask << 1) { |
|
Kevin Millikin (Chromium)
2008/10/17 09:02:41
Need a space after 'for'.
| |
| 2330 // Loop over all the bits in the remembered set word. Though | |
| 2331 // remembered sets are sparse, faster (eg, binary) search for | |
| 2332 // set bits does not seem to help much here. | |
| 2333 for (int bit_offset = 0; bit_offset < kBitsPerInt; bit_offset++) { | |
| 2334 uint32_t bitmask = 1 << bit_offset; | |
| 2335 // Do not dereference pointers at or past object_end. | 2326 // Do not dereference pointers at or past object_end. |
| 2336 if ((rset_word & bitmask) != 0 && object_address < object_end) { | 2327 if ((rset_word & bitmask) != 0 && object_address < object_end) { |
| 2337 Object** object_p = reinterpret_cast<Object**>(object_address); | 2328 Object** object_p = reinterpret_cast<Object**>(object_address); |
| 2338 if (Heap::InFromSpace(*object_p)) { | 2329 if (Heap::InNewSpace(*object_p)) { |
| 2339 copy_object_func(reinterpret_cast<HeapObject**>(object_p)); | 2330 copy_object_func(reinterpret_cast<HeapObject**>(object_p)); |
| 2340 } | 2331 } |
| 2341 // If this pointer does not need to be remembered anymore, clear | 2332 // If this pointer does not need to be remembered anymore, clear |
| 2342 // the remembered set bit. | 2333 // the remembered set bit. |
| 2343 if (!Heap::InToSpace(*object_p)) result_rset &= ~bitmask; | 2334 if (!Heap::InNewSpace(*object_p)) result_rset &= ~bitmask; |
| 2344 } | 2335 } |
| 2345 object_address += kPointerSize; | 2336 object_address += kPointerSize; |
| 2346 } | 2337 } |
| 2347 | |
| 2348 // Update the remembered set if it has changed. | 2338 // Update the remembered set if it has changed. |
| 2349 if (result_rset != rset_word) { | 2339 if (result_rset != rset_word) { |
| 2350 Memory::uint32_at(rset_address) = result_rset; | 2340 Memory::uint32_at(rset_address) = result_rset; |
| 2351 } | 2341 } |
| 2352 } else { | 2342 } else { |
| 2353 // No bits in the word were set. This is the common case. | 2343 // No bits in the word were set. This is the common case. |
| 2354 object_address += kPointerSize * kBitsPerInt; | 2344 object_address += kPointerSize * kBitsPerInt; |
| 2355 } | 2345 } |
| 2356 | |
| 2357 rset_address += kIntSize; | 2346 rset_address += kIntSize; |
| 2358 } | 2347 } |
| 2359 } | 2348 } |
| 2360 | 2349 |
| 2361 | 2350 |
| 2362 void Heap::IterateRSet(PagedSpace* space, ObjectSlotCallback copy_object_func) { | 2351 void Heap::IterateRSet(PagedSpace* space, ObjectSlotCallback copy_object_func) { |
| 2363 ASSERT(Page::is_rset_in_use()); | 2352 ASSERT(Page::is_rset_in_use()); |
| 2364 ASSERT(space == old_pointer_space_ || space == map_space_); | 2353 ASSERT(space == old_pointer_space_ || space == map_space_); |
| 2365 | 2354 |
| 2366 PageIterator it(space, PageIterator::PAGES_IN_USE); | 2355 PageIterator it(space, PageIterator::PAGES_IN_USE); |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2510 // code space. Align the pair of semispaces to their size, which must be | 2499 // code space. Align the pair of semispaces to their size, which must be |
| 2511 // a power of 2. | 2500 // a power of 2. |
| 2512 ASSERT(IsPowerOf2(young_generation_size_)); | 2501 ASSERT(IsPowerOf2(young_generation_size_)); |
| 2513 Address code_space_start = reinterpret_cast<Address>(chunk); | 2502 Address code_space_start = reinterpret_cast<Address>(chunk); |
| 2514 Address new_space_start = RoundUp(code_space_start, young_generation_size_); | 2503 Address new_space_start = RoundUp(code_space_start, young_generation_size_); |
| 2515 Address old_space_start = new_space_start + young_generation_size_; | 2504 Address old_space_start = new_space_start + young_generation_size_; |
| 2516 int code_space_size = new_space_start - code_space_start; | 2505 int code_space_size = new_space_start - code_space_start; |
| 2517 int old_space_size = young_generation_size_ - code_space_size; | 2506 int old_space_size = young_generation_size_ - code_space_size; |
| 2518 | 2507 |
| 2519 // Initialize new space. | 2508 // Initialize new space. |
| 2520 new_space_ = new NewSpace(initial_semispace_size_, | 2509 if (!new_space_.Setup(new_space_start, young_generation_size_)) return false; |
| 2521 semispace_size_, | |
| 2522 NEW_SPACE); | |
| 2523 if (new_space_ == NULL) return false; | |
| 2524 if (!new_space_->Setup(new_space_start, young_generation_size_)) return false; | |
| 2525 | 2510 |
| 2526 // Initialize old space, set the maximum capacity to the old generation | 2511 // Initialize old space, set the maximum capacity to the old generation |
| 2527 // size. It will not contain code. | 2512 // size. It will not contain code. |
| 2528 old_pointer_space_ = | 2513 old_pointer_space_ = |
| 2529 new OldSpace(old_generation_size_, OLD_POINTER_SPACE, NOT_EXECUTABLE); | 2514 new OldSpace(old_generation_size_, OLD_POINTER_SPACE, NOT_EXECUTABLE); |
| 2530 if (old_pointer_space_ == NULL) return false; | 2515 if (old_pointer_space_ == NULL) return false; |
| 2531 if (!old_pointer_space_->Setup(old_space_start, old_space_size >> 1)) { | 2516 if (!old_pointer_space_->Setup(old_space_start, old_space_size >> 1)) { |
| 2532 return false; | 2517 return false; |
| 2533 } | 2518 } |
| 2534 old_data_space_ = | 2519 old_data_space_ = |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2572 LOG(IntEvent("heap-capacity", Capacity())); | 2557 LOG(IntEvent("heap-capacity", Capacity())); |
| 2573 LOG(IntEvent("heap-available", Available())); | 2558 LOG(IntEvent("heap-available", Available())); |
| 2574 | 2559 |
| 2575 return true; | 2560 return true; |
| 2576 } | 2561 } |
| 2577 | 2562 |
| 2578 | 2563 |
| 2579 void Heap::TearDown() { | 2564 void Heap::TearDown() { |
| 2580 GlobalHandles::TearDown(); | 2565 GlobalHandles::TearDown(); |
| 2581 | 2566 |
| 2582 if (new_space_ != NULL) { | 2567 new_space_.TearDown(); |
| 2583 new_space_->TearDown(); | |
| 2584 delete new_space_; | |
| 2585 new_space_ = NULL; | |
| 2586 } | |
| 2587 | 2568 |
| 2588 if (old_pointer_space_ != NULL) { | 2569 if (old_pointer_space_ != NULL) { |
| 2589 old_pointer_space_->TearDown(); | 2570 old_pointer_space_->TearDown(); |
| 2590 delete old_pointer_space_; | 2571 delete old_pointer_space_; |
| 2591 old_pointer_space_ = NULL; | 2572 old_pointer_space_ = NULL; |
| 2592 } | 2573 } |
| 2593 | 2574 |
| 2594 if (old_data_space_ != NULL) { | 2575 if (old_data_space_ != NULL) { |
| 2595 old_data_space_->TearDown(); | 2576 old_data_space_->TearDown(); |
| 2596 delete old_data_space_; | 2577 delete old_data_space_; |
| (...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3084 return "Scavenge"; | 3065 return "Scavenge"; |
| 3085 case MARK_COMPACTOR: | 3066 case MARK_COMPACTOR: |
| 3086 return MarkCompactCollector::HasCompacted() ? "Mark-compact" | 3067 return MarkCompactCollector::HasCompacted() ? "Mark-compact" |
| 3087 : "Mark-sweep"; | 3068 : "Mark-sweep"; |
| 3088 } | 3069 } |
| 3089 return "Unknown GC"; | 3070 return "Unknown GC"; |
| 3090 } | 3071 } |
| 3091 | 3072 |
| 3092 | 3073 |
| 3093 } } // namespace v8::internal | 3074 } } // namespace v8::internal |
| OLD | NEW |