| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/heap.h" | 5 #include "vm/heap.h" |
| 6 | 6 |
| 7 #include "platform/assert.h" | 7 #include "platform/assert.h" |
| 8 #include "platform/utils.h" | 8 #include "platform/utils.h" |
| 9 #include "vm/flags.h" | 9 #include "vm/flags.h" |
| 10 #include "vm/isolate.h" | 10 #include "vm/isolate.h" |
| (...skipping 30 matching lines...) Expand all Loading... |
| 41 DEFINE_FLAG(bool, verify_before_gc, false, | 41 DEFINE_FLAG(bool, verify_before_gc, false, |
| 42 "Enables heap verification before GC."); | 42 "Enables heap verification before GC."); |
| 43 DEFINE_FLAG(bool, pretenure_all, false, "Global pretenuring (for testing)."); | 43 DEFINE_FLAG(bool, pretenure_all, false, "Global pretenuring (for testing)."); |
| 44 | 44 |
| 45 | 45 |
| 46 Heap::Heap(Isolate* isolate, | 46 Heap::Heap(Isolate* isolate, |
| 47 intptr_t max_new_gen_semi_words, | 47 intptr_t max_new_gen_semi_words, |
| 48 intptr_t max_old_gen_words, | 48 intptr_t max_old_gen_words, |
| 49 intptr_t max_external_words) | 49 intptr_t max_external_words) |
| 50 : isolate_(isolate), | 50 : isolate_(isolate), |
| 51 new_space_(this, max_new_gen_semi_words, kNewObjectAlignmentOffset), |
| 52 old_space_(this, max_old_gen_words, max_external_words), |
| 51 read_only_(false), | 53 read_only_(false), |
| 52 gc_in_progress_(false), | 54 gc_in_progress_(false), |
| 53 pretenure_policy_(0) { | 55 pretenure_policy_(0) { |
| 54 for (int sel = 0; | 56 for (int sel = 0; |
| 55 sel < kNumWeakSelectors; | 57 sel < kNumWeakSelectors; |
| 56 sel++) { | 58 sel++) { |
| 57 new_weak_tables_[sel] = new WeakTable(); | 59 new_weak_tables_[sel] = new WeakTable(); |
| 58 old_weak_tables_[sel] = new WeakTable(); | 60 old_weak_tables_[sel] = new WeakTable(); |
| 59 } | 61 } |
| 60 new_space_ = new Scavenger(this, | |
| 61 max_new_gen_semi_words, | |
| 62 kNewObjectAlignmentOffset); | |
| 63 old_space_ = new PageSpace(this, max_old_gen_words, max_external_words); | |
| 64 stats_.num_ = 0; | 62 stats_.num_ = 0; |
| 65 } | 63 } |
| 66 | 64 |
| 67 | 65 |
| 68 Heap::~Heap() { | 66 Heap::~Heap() { |
| 69 delete new_space_; | |
| 70 delete old_space_; | |
| 71 for (int sel = 0; | 67 for (int sel = 0; |
| 72 sel < kNumWeakSelectors; | 68 sel < kNumWeakSelectors; |
| 73 sel++) { | 69 sel++) { |
| 74 delete new_weak_tables_[sel]; | 70 delete new_weak_tables_[sel]; |
| 75 delete old_weak_tables_[sel]; | 71 delete old_weak_tables_[sel]; |
| 76 } | 72 } |
| 77 } | 73 } |
| 78 | 74 |
| 79 | 75 |
| 80 uword Heap::AllocateNew(intptr_t size) { | 76 uword Heap::AllocateNew(intptr_t size) { |
| 81 ASSERT(isolate()->no_safepoint_scope_depth() == 0); | 77 ASSERT(isolate()->no_safepoint_scope_depth() == 0); |
| 82 uword addr = new_space_->TryAllocate(size); | 78 uword addr = new_space_.TryAllocate(size); |
| 83 if (addr == 0) { | 79 if (addr == 0) { |
| 84 CollectGarbage(kNew); | 80 CollectGarbage(kNew); |
| 85 addr = new_space_->TryAllocate(size); | 81 addr = new_space_.TryAllocate(size); |
| 86 if (addr == 0) { | 82 if (addr == 0) { |
| 87 return AllocateOld(size, HeapPage::kData); | 83 return AllocateOld(size, HeapPage::kData); |
| 88 } | 84 } |
| 89 } | 85 } |
| 90 return addr; | 86 return addr; |
| 91 } | 87 } |
| 92 | 88 |
| 93 | 89 |
| 94 uword Heap::AllocateOld(intptr_t size, HeapPage::PageType type) { | 90 uword Heap::AllocateOld(intptr_t size, HeapPage::PageType type) { |
| 95 ASSERT(isolate()->no_safepoint_scope_depth() == 0); | 91 ASSERT(isolate()->no_safepoint_scope_depth() == 0); |
| 96 uword addr = old_space_->TryAllocate(size, type); | 92 uword addr = old_space_.TryAllocate(size, type); |
| 97 if (addr != 0) { | 93 if (addr != 0) { |
| 98 return addr; | 94 return addr; |
| 99 } | 95 } |
| 100 // If we are in the process of running a sweep wait for the sweeper to free | 96 // If we are in the process of running a sweep wait for the sweeper to free |
| 101 // memory. | 97 // memory. |
| 102 { | 98 { |
| 103 MonitorLocker ml(old_space_->tasks_lock()); | 99 MonitorLocker ml(old_space_.tasks_lock()); |
| 104 addr = old_space_->TryAllocate(size, type); | 100 addr = old_space_.TryAllocate(size, type); |
| 105 while ((addr == 0) && (old_space_->tasks() > 0)) { | 101 while ((addr == 0) && (old_space_.tasks() > 0)) { |
| 106 ml.Wait(); | 102 ml.Wait(); |
| 107 addr = old_space_->TryAllocate(size, type); | 103 addr = old_space_.TryAllocate(size, type); |
| 108 } | 104 } |
| 109 } | 105 } |
| 110 if (addr != 0) { | 106 if (addr != 0) { |
| 111 return addr; | 107 return addr; |
| 112 } | 108 } |
| 113 // All GC tasks finished without allocating successfully. Run a full GC. | 109 // All GC tasks finished without allocating successfully. Run a full GC. |
| 114 CollectAllGarbage(); | 110 CollectAllGarbage(); |
| 115 addr = old_space_->TryAllocate(size, type); | 111 addr = old_space_.TryAllocate(size, type); |
| 116 if (addr != 0) { | 112 if (addr != 0) { |
| 117 return addr; | 113 return addr; |
| 118 } | 114 } |
| 119 // Wait for all of the concurrent tasks to finish before giving up. | 115 // Wait for all of the concurrent tasks to finish before giving up. |
| 120 { | 116 { |
| 121 MonitorLocker ml(old_space_->tasks_lock()); | 117 MonitorLocker ml(old_space_.tasks_lock()); |
| 122 addr = old_space_->TryAllocate(size, type); | 118 addr = old_space_.TryAllocate(size, type); |
| 123 while ((addr == 0) && (old_space_->tasks() > 0)) { | 119 while ((addr == 0) && (old_space_.tasks() > 0)) { |
| 124 ml.Wait(); | 120 ml.Wait(); |
| 125 addr = old_space_->TryAllocate(size, type); | 121 addr = old_space_.TryAllocate(size, type); |
| 126 } | 122 } |
| 127 } | 123 } |
| 128 if (addr != 0) { | 124 if (addr != 0) { |
| 129 return addr; | 125 return addr; |
| 130 } | 126 } |
| 131 // Force growth before attempting a synchronous GC. | 127 // Force growth before attempting a synchronous GC. |
| 132 addr = old_space_->TryAllocate(size, type, PageSpace::kForceGrowth); | 128 addr = old_space_.TryAllocate(size, type, PageSpace::kForceGrowth); |
| 133 if (addr != 0) { | 129 if (addr != 0) { |
| 134 return addr; | 130 return addr; |
| 135 } | 131 } |
| 136 // Before throwing an out-of-memory error try a synchronous GC. | 132 // Before throwing an out-of-memory error try a synchronous GC. |
| 137 CollectAllGarbage(); | 133 CollectAllGarbage(); |
| 138 { | 134 { |
| 139 MonitorLocker ml(old_space_->tasks_lock()); | 135 MonitorLocker ml(old_space_.tasks_lock()); |
| 140 while (old_space_->tasks() > 0) { | 136 while (old_space_.tasks() > 0) { |
| 141 ml.Wait(); | 137 ml.Wait(); |
| 142 } | 138 } |
| 143 } | 139 } |
| 144 addr = old_space_->TryAllocate(size, type, PageSpace::kForceGrowth); | 140 addr = old_space_.TryAllocate(size, type, PageSpace::kForceGrowth); |
| 145 if (addr != 0) { | 141 if (addr != 0) { |
| 146 return addr; | 142 return addr; |
| 147 } | 143 } |
| 148 // Give up allocating this object. | 144 // Give up allocating this object. |
| 149 OS::PrintErr( | 145 OS::PrintErr( |
| 150 "Exhausted heap space, trying to allocate %" Pd " bytes.\n", size); | 146 "Exhausted heap space, trying to allocate %" Pd " bytes.\n", size); |
| 151 return 0; | 147 return 0; |
| 152 } | 148 } |
| 153 | 149 |
| 154 | 150 |
| 155 uword Heap::AllocatePretenured(intptr_t size) { | 151 uword Heap::AllocatePretenured(intptr_t size) { |
| 156 ASSERT(isolate()->no_safepoint_scope_depth() == 0); | 152 ASSERT(isolate()->no_safepoint_scope_depth() == 0); |
| 157 uword addr = old_space_->TryAllocateDataBump(size, PageSpace::kControlGrowth); | 153 uword addr = old_space_.TryAllocateDataBump(size, PageSpace::kControlGrowth); |
| 158 if (addr != 0) return addr; | 154 if (addr != 0) return addr; |
| 159 return AllocateOld(size, HeapPage::kData); | 155 return AllocateOld(size, HeapPage::kData); |
| 160 } | 156 } |
| 161 | 157 |
| 162 | 158 |
| 163 void Heap::AllocateExternal(intptr_t size, Space space) { | 159 void Heap::AllocateExternal(intptr_t size, Space space) { |
| 164 ASSERT(isolate()->no_safepoint_scope_depth() == 0); | 160 ASSERT(isolate()->no_safepoint_scope_depth() == 0); |
| 165 if (space == kNew) { | 161 if (space == kNew) { |
| 166 new_space_->AllocateExternal(size); | 162 new_space_.AllocateExternal(size); |
| 167 if (new_space_->ExternalInWords() > (FLAG_new_gen_ext_limit * MBInWords)) { | 163 if (new_space_.ExternalInWords() > (FLAG_new_gen_ext_limit * MBInWords)) { |
| 168 // Attempt to free some external allocation by a scavenge. (If the total | 164 // Attempt to free some external allocation by a scavenge. (If the total |
| 169 // remains above the limit, next external alloc will trigger another.) | 165 // remains above the limit, next external alloc will trigger another.) |
| 170 CollectGarbage(kNew); | 166 CollectGarbage(kNew); |
| 171 } | 167 } |
| 172 } else { | 168 } else { |
| 173 ASSERT(space == kOld); | 169 ASSERT(space == kOld); |
| 174 old_space_->AllocateExternal(size); | 170 old_space_.AllocateExternal(size); |
| 175 if (old_space_->NeedsGarbageCollection()) { | 171 if (old_space_.NeedsGarbageCollection()) { |
| 176 CollectAllGarbage(); | 172 CollectAllGarbage(); |
| 177 } | 173 } |
| 178 } | 174 } |
| 179 } | 175 } |
| 180 | 176 |
| 181 void Heap::FreeExternal(intptr_t size, Space space) { | 177 void Heap::FreeExternal(intptr_t size, Space space) { |
| 182 if (space == kNew) { | 178 if (space == kNew) { |
| 183 new_space_->FreeExternal(size); | 179 new_space_.FreeExternal(size); |
| 184 } else { | 180 } else { |
| 185 ASSERT(space == kOld); | 181 ASSERT(space == kOld); |
| 186 old_space_->FreeExternal(size); | 182 old_space_.FreeExternal(size); |
| 187 } | 183 } |
| 188 } | 184 } |
| 189 | 185 |
| 190 void Heap::PromoteExternal(intptr_t size) { | 186 void Heap::PromoteExternal(intptr_t size) { |
| 191 new_space_->FreeExternal(size); | 187 new_space_.FreeExternal(size); |
| 192 old_space_->AllocateExternal(size); | 188 old_space_.AllocateExternal(size); |
| 193 } | 189 } |
| 194 | 190 |
| 195 bool Heap::Contains(uword addr) const { | 191 bool Heap::Contains(uword addr) const { |
| 196 return new_space_->Contains(addr) || | 192 return new_space_.Contains(addr) || |
| 197 old_space_->Contains(addr); | 193 old_space_.Contains(addr); |
| 198 } | 194 } |
| 199 | 195 |
| 200 | 196 |
| 201 bool Heap::NewContains(uword addr) const { | 197 bool Heap::NewContains(uword addr) const { |
| 202 return new_space_->Contains(addr); | 198 return new_space_.Contains(addr); |
| 203 } | 199 } |
| 204 | 200 |
| 205 | 201 |
| 206 bool Heap::OldContains(uword addr) const { | 202 bool Heap::OldContains(uword addr) const { |
| 207 return old_space_->Contains(addr); | 203 return old_space_.Contains(addr); |
| 208 } | 204 } |
| 209 | 205 |
| 210 | 206 |
| 211 bool Heap::CodeContains(uword addr) const { | 207 bool Heap::CodeContains(uword addr) const { |
| 212 return old_space_->Contains(addr, HeapPage::kExecutable); | 208 return old_space_.Contains(addr, HeapPage::kExecutable); |
| 213 } | 209 } |
| 214 | 210 |
| 215 | 211 |
| 216 void Heap::VisitObjects(ObjectVisitor* visitor) const { | 212 void Heap::VisitObjects(ObjectVisitor* visitor) const { |
| 217 new_space_->VisitObjects(visitor); | 213 new_space_.VisitObjects(visitor); |
| 218 old_space_->VisitObjects(visitor); | 214 old_space_.VisitObjects(visitor); |
| 219 } | 215 } |
| 220 | 216 |
| 221 | 217 |
| 222 HeapIterationScope::HeapIterationScope() | 218 HeapIterationScope::HeapIterationScope() |
| 223 : StackResource(Thread::Current()->isolate()), | 219 : StackResource(Thread::Current()->isolate()), |
| 224 old_space_(isolate()->heap()->old_space()) { | 220 old_space_(isolate()->heap()->old_space()) { |
| 225 // It's not yet safe to iterate over a paged space while it's concurrently | 221 // It's not yet safe to iterate over a paged space while it's concurrently |
| 226 // sweeping, so wait for any such task to complete first. | 222 // sweeping, so wait for any such task to complete first. |
| 227 MonitorLocker ml(old_space_->tasks_lock()); | 223 MonitorLocker ml(old_space_->tasks_lock()); |
| 228 #if defined(DEBUG) | 224 #if defined(DEBUG) |
| (...skipping 16 matching lines...) Expand all Loading... |
| 245 #endif | 241 #endif |
| 246 ASSERT(old_space_->tasks() == 1); | 242 ASSERT(old_space_->tasks() == 1); |
| 247 old_space_->set_tasks(0); | 243 old_space_->set_tasks(0); |
| 248 ml.Notify(); | 244 ml.Notify(); |
| 249 } | 245 } |
| 250 | 246 |
| 251 | 247 |
| 252 void Heap::IterateObjects(ObjectVisitor* visitor) const { | 248 void Heap::IterateObjects(ObjectVisitor* visitor) const { |
| 253 // The visitor must not allocate from the heap. | 249 // The visitor must not allocate from the heap. |
| 254 NoSafepointScope no_safepoint_scope_; | 250 NoSafepointScope no_safepoint_scope_; |
| 255 new_space_->VisitObjects(visitor); | 251 new_space_.VisitObjects(visitor); |
| 256 IterateOldObjects(visitor); | 252 IterateOldObjects(visitor); |
| 257 } | 253 } |
| 258 | 254 |
| 259 | 255 |
| 260 void Heap::IterateOldObjects(ObjectVisitor* visitor) const { | 256 void Heap::IterateOldObjects(ObjectVisitor* visitor) const { |
| 261 HeapIterationScope heap_iteration_scope; | 257 HeapIterationScope heap_iteration_scope; |
| 262 old_space_->VisitObjects(visitor); | 258 old_space_.VisitObjects(visitor); |
| 263 } | 259 } |
| 264 | 260 |
| 265 | 261 |
| 266 void Heap::VisitObjectPointers(ObjectPointerVisitor* visitor) const { | 262 void Heap::VisitObjectPointers(ObjectPointerVisitor* visitor) const { |
| 267 new_space_->VisitObjectPointers(visitor); | 263 new_space_.VisitObjectPointers(visitor); |
| 268 old_space_->VisitObjectPointers(visitor); | 264 old_space_.VisitObjectPointers(visitor); |
| 269 } | 265 } |
| 270 | 266 |
| 271 | 267 |
| 272 RawInstructions* Heap::FindObjectInCodeSpace(FindObjectVisitor* visitor) const { | 268 RawInstructions* Heap::FindObjectInCodeSpace(FindObjectVisitor* visitor) const { |
| 273 // Only executable pages can have RawInstructions objects. | 269 // Only executable pages can have RawInstructions objects. |
| 274 RawObject* raw_obj = old_space_->FindObject(visitor, HeapPage::kExecutable); | 270 RawObject* raw_obj = old_space_.FindObject(visitor, HeapPage::kExecutable); |
| 275 ASSERT((raw_obj == Object::null()) || | 271 ASSERT((raw_obj == Object::null()) || |
| 276 (raw_obj->GetClassId() == kInstructionsCid)); | 272 (raw_obj->GetClassId() == kInstructionsCid)); |
| 277 return reinterpret_cast<RawInstructions*>(raw_obj); | 273 return reinterpret_cast<RawInstructions*>(raw_obj); |
| 278 } | 274 } |
| 279 | 275 |
| 280 | 276 |
| 281 RawObject* Heap::FindOldObject(FindObjectVisitor* visitor) const { | 277 RawObject* Heap::FindOldObject(FindObjectVisitor* visitor) const { |
| 282 HeapIterationScope heap_iteration_scope; | 278 HeapIterationScope heap_iteration_scope; |
| 283 return old_space_->FindObject(visitor, HeapPage::kData); | 279 return old_space_.FindObject(visitor, HeapPage::kData); |
| 284 } | 280 } |
| 285 | 281 |
| 286 | 282 |
| 287 RawObject* Heap::FindNewObject(FindObjectVisitor* visitor) const { | 283 RawObject* Heap::FindNewObject(FindObjectVisitor* visitor) const { |
| 288 return new_space_->FindObject(visitor); | 284 return new_space_.FindObject(visitor); |
| 289 } | 285 } |
| 290 | 286 |
| 291 | 287 |
| 292 RawObject* Heap::FindObject(FindObjectVisitor* visitor) const { | 288 RawObject* Heap::FindObject(FindObjectVisitor* visitor) const { |
| 293 // The visitor must not allocate from the heap. | 289 // The visitor must not allocate from the heap. |
| 294 NoSafepointScope no_safepoint_scope; | 290 NoSafepointScope no_safepoint_scope; |
| 295 RawObject* raw_obj = FindNewObject(visitor); | 291 RawObject* raw_obj = FindNewObject(visitor); |
| 296 if (raw_obj != Object::null()) { | 292 if (raw_obj != Object::null()) { |
| 297 return raw_obj; | 293 return raw_obj; |
| 298 } | 294 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 311 TIMERSCOPE(isolate(), time_gc); | 307 TIMERSCOPE(isolate(), time_gc); |
| 312 bool invoke_api_callbacks = (api_callbacks == kInvokeApiCallbacks); | 308 bool invoke_api_callbacks = (api_callbacks == kInvokeApiCallbacks); |
| 313 switch (space) { | 309 switch (space) { |
| 314 case kNew: { | 310 case kNew: { |
| 315 VMTagScope tagScope(isolate(), VMTag::kGCNewSpaceTagId); | 311 VMTagScope tagScope(isolate(), VMTag::kGCNewSpaceTagId); |
| 316 TimelineDurationScope tds(isolate(), | 312 TimelineDurationScope tds(isolate(), |
| 317 isolate()->GetGCStream(), | 313 isolate()->GetGCStream(), |
| 318 "CollectNewGeneration"); | 314 "CollectNewGeneration"); |
| 319 RecordBeforeGC(kNew, reason); | 315 RecordBeforeGC(kNew, reason); |
| 320 UpdateClassHeapStatsBeforeGC(kNew); | 316 UpdateClassHeapStatsBeforeGC(kNew); |
| 321 new_space_->Scavenge(invoke_api_callbacks); | 317 new_space_.Scavenge(invoke_api_callbacks); |
| 322 isolate()->class_table()->UpdatePromoted(); | 318 isolate()->class_table()->UpdatePromoted(); |
| 323 UpdatePretenurePolicy(); | 319 UpdatePretenurePolicy(); |
| 324 RecordAfterGC(); | 320 RecordAfterGC(); |
| 325 PrintStats(); | 321 PrintStats(); |
| 326 if (old_space_->NeedsGarbageCollection()) { | 322 if (old_space_.NeedsGarbageCollection()) { |
| 327 // Old collections should call the API callbacks. | 323 // Old collections should call the API callbacks. |
| 328 CollectGarbage(kOld, kInvokeApiCallbacks, kPromotion); | 324 CollectGarbage(kOld, kInvokeApiCallbacks, kPromotion); |
| 329 } | 325 } |
| 330 break; | 326 break; |
| 331 } | 327 } |
| 332 case kOld: | 328 case kOld: |
| 333 case kCode: { | 329 case kCode: { |
| 334 VMTagScope tagScope(isolate(), VMTag::kGCOldSpaceTagId); | 330 VMTagScope tagScope(isolate(), VMTag::kGCOldSpaceTagId); |
| 335 TimelineDurationScope tds(isolate(), | 331 TimelineDurationScope tds(isolate(), |
| 336 isolate()->GetGCStream(), | 332 isolate()->GetGCStream(), |
| 337 "CollectOldGeneration"); | 333 "CollectOldGeneration"); |
| 338 RecordBeforeGC(kOld, reason); | 334 RecordBeforeGC(kOld, reason); |
| 339 UpdateClassHeapStatsBeforeGC(kOld); | 335 UpdateClassHeapStatsBeforeGC(kOld); |
| 340 old_space_->MarkSweep(invoke_api_callbacks); | 336 old_space_.MarkSweep(invoke_api_callbacks); |
| 341 RecordAfterGC(); | 337 RecordAfterGC(); |
| 342 PrintStats(); | 338 PrintStats(); |
| 343 break; | 339 break; |
| 344 } | 340 } |
| 345 default: | 341 default: |
| 346 UNREACHABLE(); | 342 UNREACHABLE(); |
| 347 } | 343 } |
| 348 } | 344 } |
| 349 | 345 |
| 350 | 346 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 370 | 366 |
| 371 void Heap::CollectAllGarbage() { | 367 void Heap::CollectAllGarbage() { |
| 372 TIMERSCOPE(isolate(), time_gc); | 368 TIMERSCOPE(isolate(), time_gc); |
| 373 { | 369 { |
| 374 VMTagScope tagScope(isolate(), VMTag::kGCNewSpaceTagId); | 370 VMTagScope tagScope(isolate(), VMTag::kGCNewSpaceTagId); |
| 375 TimelineDurationScope tds(isolate(), | 371 TimelineDurationScope tds(isolate(), |
| 376 isolate()->GetGCStream(), | 372 isolate()->GetGCStream(), |
| 377 "CollectNewGeneration"); | 373 "CollectNewGeneration"); |
| 378 RecordBeforeGC(kNew, kFull); | 374 RecordBeforeGC(kNew, kFull); |
| 379 UpdateClassHeapStatsBeforeGC(kNew); | 375 UpdateClassHeapStatsBeforeGC(kNew); |
| 380 new_space_->Scavenge(kInvokeApiCallbacks); | 376 new_space_.Scavenge(kInvokeApiCallbacks); |
| 381 isolate()->class_table()->UpdatePromoted(); | 377 isolate()->class_table()->UpdatePromoted(); |
| 382 UpdatePretenurePolicy(); | 378 UpdatePretenurePolicy(); |
| 383 RecordAfterGC(); | 379 RecordAfterGC(); |
| 384 PrintStats(); | 380 PrintStats(); |
| 385 } | 381 } |
| 386 { | 382 { |
| 387 VMTagScope tagScope(isolate(), VMTag::kGCOldSpaceTagId); | 383 VMTagScope tagScope(isolate(), VMTag::kGCOldSpaceTagId); |
| 388 TimelineDurationScope tds(isolate(), | 384 TimelineDurationScope tds(isolate(), |
| 389 isolate()->GetGCStream(), | 385 isolate()->GetGCStream(), |
| 390 "CollectOldGeneration"); | 386 "CollectOldGeneration"); |
| 391 RecordBeforeGC(kOld, kFull); | 387 RecordBeforeGC(kOld, kFull); |
| 392 UpdateClassHeapStatsBeforeGC(kOld); | 388 UpdateClassHeapStatsBeforeGC(kOld); |
| 393 old_space_->MarkSweep(kInvokeApiCallbacks); | 389 old_space_.MarkSweep(kInvokeApiCallbacks); |
| 394 RecordAfterGC(); | 390 RecordAfterGC(); |
| 395 PrintStats(); | 391 PrintStats(); |
| 396 } | 392 } |
| 397 } | 393 } |
| 398 | 394 |
| 399 | 395 |
| 400 bool Heap::ShouldPretenure(intptr_t class_id) const { | 396 bool Heap::ShouldPretenure(intptr_t class_id) const { |
| 401 if (class_id == kOneByteStringCid) { | 397 if (class_id == kOneByteStringCid) { |
| 402 return pretenure_policy_ > 0; | 398 return pretenure_policy_ > 0; |
| 403 } else { | 399 } else { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 425 (100 * stats->promoted_count) / allocated; | 421 (100 * stats->promoted_count) / allocated; |
| 426 if (promo_percent >= FLAG_pretenure_threshold) { | 422 if (promo_percent >= FLAG_pretenure_threshold) { |
| 427 pretenure_policy_ += FLAG_pretenure_interval; | 423 pretenure_policy_ += FLAG_pretenure_interval; |
| 428 } else { | 424 } else { |
| 429 pretenure_policy_ = Utils::Maximum(0, pretenure_policy_ - 1); | 425 pretenure_policy_ = Utils::Maximum(0, pretenure_policy_ - 1); |
| 430 } | 426 } |
| 431 } | 427 } |
| 432 | 428 |
| 433 | 429 |
| 434 void Heap::SetGrowthControlState(bool state) { | 430 void Heap::SetGrowthControlState(bool state) { |
| 435 old_space_->SetGrowthControlState(state); | 431 old_space_.SetGrowthControlState(state); |
| 436 } | 432 } |
| 437 | 433 |
| 438 | 434 |
| 439 bool Heap::GrowthControlState() { | 435 bool Heap::GrowthControlState() { |
| 440 return old_space_->GrowthControlState(); | 436 return old_space_.GrowthControlState(); |
| 441 } | 437 } |
| 442 | 438 |
| 443 | 439 |
| 444 void Heap::WriteProtect(bool read_only) { | 440 void Heap::WriteProtect(bool read_only) { |
| 445 read_only_ = read_only; | 441 read_only_ = read_only; |
| 446 new_space_->WriteProtect(read_only); | 442 new_space_.WriteProtect(read_only); |
| 447 old_space_->WriteProtect(read_only); | 443 old_space_.WriteProtect(read_only); |
| 448 } | 444 } |
| 449 | 445 |
| 450 | 446 |
| 451 uword Heap::TopAddress(Heap::Space space) { | 447 uword Heap::TopAddress(Heap::Space space) { |
| 452 if (space == kNew) { | 448 if (space == kNew) { |
| 453 return reinterpret_cast<uword>(new_space_->TopAddress()); | 449 return reinterpret_cast<uword>(new_space_.TopAddress()); |
| 454 } else { | 450 } else { |
| 455 ASSERT(space == kPretenured); | 451 ASSERT(space == kPretenured); |
| 456 return reinterpret_cast<uword>(old_space_->TopAddress()); | 452 return reinterpret_cast<uword>(old_space_.TopAddress()); |
| 457 } | 453 } |
| 458 } | 454 } |
| 459 | 455 |
| 460 | 456 |
| 461 uword Heap::EndAddress(Heap::Space space) { | 457 uword Heap::EndAddress(Heap::Space space) { |
| 462 if (space == kNew) { | 458 if (space == kNew) { |
| 463 return reinterpret_cast<uword>(new_space_->EndAddress()); | 459 return reinterpret_cast<uword>(new_space_.EndAddress()); |
| 464 } else { | 460 } else { |
| 465 ASSERT(space == kPretenured); | 461 ASSERT(space == kPretenured); |
| 466 return reinterpret_cast<uword>(old_space_->EndAddress()); | 462 return reinterpret_cast<uword>(old_space_.EndAddress()); |
| 467 } | 463 } |
| 468 } | 464 } |
| 469 | 465 |
| 470 | 466 |
| 471 Heap::Space Heap::SpaceForAllocation(intptr_t cid) const { | 467 Heap::Space Heap::SpaceForAllocation(intptr_t cid) const { |
| 472 return FLAG_pretenure_all ? kPretenured : kNew; | 468 return FLAG_pretenure_all ? kPretenured : kNew; |
| 473 } | 469 } |
| 474 | 470 |
| 475 | 471 |
| 476 void Heap::Init(Isolate* isolate, | 472 void Heap::Init(Isolate* isolate, |
| 477 intptr_t max_new_gen_words, | 473 intptr_t max_new_gen_words, |
| 478 intptr_t max_old_gen_words, | 474 intptr_t max_old_gen_words, |
| 479 intptr_t max_external_words) { | 475 intptr_t max_external_words) { |
| 480 ASSERT(isolate->heap() == NULL); | 476 ASSERT(isolate->heap() == NULL); |
| 481 Heap* heap = new Heap(isolate, | 477 Heap* heap = new Heap(isolate, |
| 482 max_new_gen_words, | 478 max_new_gen_words, |
| 483 max_old_gen_words, | 479 max_old_gen_words, |
| 484 max_external_words); | 480 max_external_words); |
| 485 isolate->set_heap(heap); | 481 isolate->set_heap(heap); |
| 486 } | 482 } |
| 487 | 483 |
| 488 | 484 |
| 489 void Heap::GetMergedAddressRange(uword* start, uword* end) const { | 485 void Heap::GetMergedAddressRange(uword* start, uword* end) const { |
| 490 if (new_space_->CapacityInWords() != 0) { | 486 if (new_space_.CapacityInWords() != 0) { |
| 491 uword new_start; | 487 uword new_start; |
| 492 uword new_end; | 488 uword new_end; |
| 493 new_space_->StartEndAddress(&new_start, &new_end); | 489 new_space_.StartEndAddress(&new_start, &new_end); |
| 494 *start = Utils::Minimum(new_start, *start); | 490 *start = Utils::Minimum(new_start, *start); |
| 495 *end = Utils::Maximum(new_end, *end); | 491 *end = Utils::Maximum(new_end, *end); |
| 496 } | 492 } |
| 497 if (old_space_->CapacityInWords() != 0) { | 493 if (old_space_.CapacityInWords() != 0) { |
| 498 uword old_start; | 494 uword old_start; |
| 499 uword old_end; | 495 uword old_end; |
| 500 old_space_->StartEndAddress(&old_start, &old_end); | 496 old_space_.StartEndAddress(&old_start, &old_end); |
| 501 *start = Utils::Minimum(old_start, *start); | 497 *start = Utils::Minimum(old_start, *start); |
| 502 *end = Utils::Maximum(old_end, *end); | 498 *end = Utils::Maximum(old_end, *end); |
| 503 } | 499 } |
| 504 ASSERT(*start <= *end); | 500 ASSERT(*start <= *end); |
| 505 } | 501 } |
| 506 | 502 |
| 507 | 503 |
| 508 ObjectSet* Heap::CreateAllocatedObjectSet( | 504 ObjectSet* Heap::CreateAllocatedObjectSet( |
| 509 MarkExpectation mark_expectation) const { | 505 MarkExpectation mark_expectation) const { |
| 510 uword start = static_cast<uword>(-1); | 506 uword start = static_cast<uword>(-1); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 549 OS::PrintErr("New space (%" Pd "k of %" Pd "k) " | 545 OS::PrintErr("New space (%" Pd "k of %" Pd "k) " |
| 550 "Old space (%" Pd "k of %" Pd "k)\n", | 546 "Old space (%" Pd "k of %" Pd "k)\n", |
| 551 (UsedInWords(kNew) / KBInWords), | 547 (UsedInWords(kNew) / KBInWords), |
| 552 (CapacityInWords(kNew) / KBInWords), | 548 (CapacityInWords(kNew) / KBInWords), |
| 553 (UsedInWords(kOld) / KBInWords), | 549 (UsedInWords(kOld) / KBInWords), |
| 554 (CapacityInWords(kOld) / KBInWords)); | 550 (CapacityInWords(kOld) / KBInWords)); |
| 555 } | 551 } |
| 556 | 552 |
| 557 | 553 |
| 558 intptr_t Heap::UsedInWords(Space space) const { | 554 intptr_t Heap::UsedInWords(Space space) const { |
| 559 return space == kNew ? new_space_->UsedInWords() : old_space_->UsedInWords(); | 555 return space == kNew ? new_space_.UsedInWords() : old_space_.UsedInWords(); |
| 560 } | 556 } |
| 561 | 557 |
| 562 | 558 |
| 563 intptr_t Heap::CapacityInWords(Space space) const { | 559 intptr_t Heap::CapacityInWords(Space space) const { |
| 564 return space == kNew ? new_space_->CapacityInWords() : | 560 return space == kNew ? new_space_.CapacityInWords() : |
| 565 old_space_->CapacityInWords(); | 561 old_space_.CapacityInWords(); |
| 566 } | 562 } |
| 567 | 563 |
| 568 intptr_t Heap::ExternalInWords(Space space) const { | 564 intptr_t Heap::ExternalInWords(Space space) const { |
| 569 return space == kNew ? new_space_->ExternalInWords() : | 565 return space == kNew ? new_space_.ExternalInWords() : |
| 570 old_space_->ExternalInWords(); | 566 old_space_.ExternalInWords(); |
| 571 } | 567 } |
| 572 | 568 |
| 573 int64_t Heap::GCTimeInMicros(Space space) const { | 569 int64_t Heap::GCTimeInMicros(Space space) const { |
| 574 if (space == kNew) { | 570 if (space == kNew) { |
| 575 return new_space_->gc_time_micros(); | 571 return new_space_.gc_time_micros(); |
| 576 } | 572 } |
| 577 return old_space_->gc_time_micros(); | 573 return old_space_.gc_time_micros(); |
| 578 } | 574 } |
| 579 | 575 |
| 580 | 576 |
| 581 intptr_t Heap::Collections(Space space) const { | 577 intptr_t Heap::Collections(Space space) const { |
| 582 if (space == kNew) { | 578 if (space == kNew) { |
| 583 return new_space_->collections(); | 579 return new_space_.collections(); |
| 584 } | 580 } |
| 585 return old_space_->collections(); | 581 return old_space_.collections(); |
| 586 } | 582 } |
| 587 | 583 |
| 588 | 584 |
| 589 const char* Heap::GCReasonToString(GCReason gc_reason) { | 585 const char* Heap::GCReasonToString(GCReason gc_reason) { |
| 590 switch (gc_reason) { | 586 switch (gc_reason) { |
| 591 case kNewSpace: | 587 case kNewSpace: |
| 592 return "new space"; | 588 return "new space"; |
| 593 case kPromotion: | 589 case kPromotion: |
| 594 return "promotion"; | 590 return "promotion"; |
| 595 case kOldSpace: | 591 case kOldSpace: |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 632 new_weak_tables_[sel]->SetValue(raw_obj, val); | 628 new_weak_tables_[sel]->SetValue(raw_obj, val); |
| 633 } else { | 629 } else { |
| 634 ASSERT(raw_obj->IsOldObject()); | 630 ASSERT(raw_obj->IsOldObject()); |
| 635 old_weak_tables_[sel]->SetValue(raw_obj, val); | 631 old_weak_tables_[sel]->SetValue(raw_obj, val); |
| 636 } | 632 } |
| 637 } | 633 } |
| 638 | 634 |
| 639 | 635 |
| 640 void Heap::PrintToJSONObject(Space space, JSONObject* object) const { | 636 void Heap::PrintToJSONObject(Space space, JSONObject* object) const { |
| 641 if (space == kNew) { | 637 if (space == kNew) { |
| 642 new_space_->PrintToJSONObject(object); | 638 new_space_.PrintToJSONObject(object); |
| 643 } else { | 639 } else { |
| 644 old_space_->PrintToJSONObject(object); | 640 old_space_.PrintToJSONObject(object); |
| 645 } | 641 } |
| 646 } | 642 } |
| 647 | 643 |
| 648 | 644 |
| 649 void Heap::RecordBeforeGC(Space space, GCReason reason) { | 645 void Heap::RecordBeforeGC(Space space, GCReason reason) { |
| 650 ASSERT(!gc_in_progress_); | 646 ASSERT(!gc_in_progress_); |
| 651 gc_in_progress_ = true; | 647 gc_in_progress_ = true; |
| 652 stats_.num_++; | 648 stats_.num_++; |
| 653 stats_.space_ = space; | 649 stats_.space_ = space; |
| 654 stats_.reason_ = reason; | 650 stats_.reason_ = reason; |
| 655 stats_.before_.micros_ = OS::GetCurrentTimeMicros(); | 651 stats_.before_.micros_ = OS::GetCurrentTimeMicros(); |
| 656 stats_.before_.new_ = new_space_->GetCurrentUsage(); | 652 stats_.before_.new_ = new_space_.GetCurrentUsage(); |
| 657 stats_.before_.old_ = old_space_->GetCurrentUsage(); | 653 stats_.before_.old_ = old_space_.GetCurrentUsage(); |
| 658 stats_.times_[0] = 0; | 654 stats_.times_[0] = 0; |
| 659 stats_.times_[1] = 0; | 655 stats_.times_[1] = 0; |
| 660 stats_.times_[2] = 0; | 656 stats_.times_[2] = 0; |
| 661 stats_.times_[3] = 0; | 657 stats_.times_[3] = 0; |
| 662 stats_.data_[0] = 0; | 658 stats_.data_[0] = 0; |
| 663 stats_.data_[1] = 0; | 659 stats_.data_[1] = 0; |
| 664 stats_.data_[2] = 0; | 660 stats_.data_[2] = 0; |
| 665 stats_.data_[3] = 0; | 661 stats_.data_[3] = 0; |
| 666 } | 662 } |
| 667 | 663 |
| 668 | 664 |
| 669 void Heap::RecordAfterGC() { | 665 void Heap::RecordAfterGC() { |
| 670 stats_.after_.micros_ = OS::GetCurrentTimeMicros(); | 666 stats_.after_.micros_ = OS::GetCurrentTimeMicros(); |
| 671 int64_t delta = stats_.after_.micros_ - stats_.before_.micros_; | 667 int64_t delta = stats_.after_.micros_ - stats_.before_.micros_; |
| 672 if (stats_.space_ == kNew) { | 668 if (stats_.space_ == kNew) { |
| 673 new_space_->AddGCTime(delta); | 669 new_space_.AddGCTime(delta); |
| 674 new_space_->IncrementCollections(); | 670 new_space_.IncrementCollections(); |
| 675 } else { | 671 } else { |
| 676 old_space_->AddGCTime(delta); | 672 old_space_.AddGCTime(delta); |
| 677 old_space_->IncrementCollections(); | 673 old_space_.IncrementCollections(); |
| 678 } | 674 } |
| 679 stats_.after_.new_ = new_space_->GetCurrentUsage(); | 675 stats_.after_.new_ = new_space_.GetCurrentUsage(); |
| 680 stats_.after_.old_ = old_space_->GetCurrentUsage(); | 676 stats_.after_.old_ = old_space_.GetCurrentUsage(); |
| 681 ASSERT(gc_in_progress_); | 677 ASSERT(gc_in_progress_); |
| 682 gc_in_progress_ = false; | 678 gc_in_progress_ = false; |
| 683 if (Service::gc_stream.enabled()) { | 679 if (Service::gc_stream.enabled()) { |
| 684 ServiceEvent event(Isolate::Current(), ServiceEvent::kGC); | 680 ServiceEvent event(Isolate::Current(), ServiceEvent::kGC); |
| 685 event.set_gc_stats(&stats_); | 681 event.set_gc_stats(&stats_); |
| 686 Service::HandleEvent(&event); | 682 Service::HandleEvent(&event); |
| 687 } | 683 } |
| 688 } | 684 } |
| 689 | 685 |
| 690 | 686 |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 761 heap->DisableGrowthControl(); | 757 heap->DisableGrowthControl(); |
| 762 } | 758 } |
| 763 | 759 |
| 764 | 760 |
| 765 NoHeapGrowthControlScope::~NoHeapGrowthControlScope() { | 761 NoHeapGrowthControlScope::~NoHeapGrowthControlScope() { |
| 766 Heap* heap = reinterpret_cast<Isolate*>(isolate())->heap(); | 762 Heap* heap = reinterpret_cast<Isolate*>(isolate())->heap(); |
| 767 heap->SetGrowthControlState(current_growth_controller_state_); | 763 heap->SetGrowthControlState(current_growth_controller_state_); |
| 768 } | 764 } |
| 769 | 765 |
| 770 } // namespace dart | 766 } // namespace dart |
| OLD | NEW |