| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 ThreadHeap::~ThreadHeap() { | 164 ThreadHeap::~ThreadHeap() { |
| 165 } | 165 } |
| 166 | 166 |
| 167 #if DCHECK_IS_ON() | 167 #if DCHECK_IS_ON() |
| 168 BasePage* ThreadHeap::FindPageFromAddress(Address address) { | 168 BasePage* ThreadHeap::FindPageFromAddress(Address address) { |
| 169 return thread_state_->FindPageFromAddress(address); | 169 return thread_state_->FindPageFromAddress(address); |
| 170 } | 170 } |
| 171 #endif | 171 #endif |
| 172 | 172 |
| 173 Address ThreadHeap::CheckAndMarkPointer(Visitor* visitor, Address address) { | 173 Address ThreadHeap::CheckAndMarkPointer(Visitor* visitor, Address address) { |
| 174 ASSERT(ThreadState::Current()->IsInGC()); | 174 DCHECK(ThreadState::Current()->IsInGC()); |
| 175 | 175 |
| 176 #if !DCHECK_IS_ON() | 176 #if !DCHECK_IS_ON() |
| 177 if (heap_does_not_contain_cache_->Lookup(address)) | 177 if (heap_does_not_contain_cache_->Lookup(address)) |
| 178 return nullptr; | 178 return nullptr; |
| 179 #endif | 179 #endif |
| 180 | 180 |
| 181 if (BasePage* page = LookupPageForAddress(address)) { | 181 if (BasePage* page = LookupPageForAddress(address)) { |
| 182 ASSERT(page->Contains(address)); | 182 #if DCHECK_IS_ON() |
| 183 ASSERT(!heap_does_not_contain_cache_->Lookup(address)); | 183 DCHECK(page->Contains(address)); |
| 184 #endif |
| 185 DCHECK(!heap_does_not_contain_cache_->Lookup(address)); |
| 184 DCHECK(&visitor->Heap() == &page->Arena()->GetThreadState()->Heap()); | 186 DCHECK(&visitor->Heap() == &page->Arena()->GetThreadState()->Heap()); |
| 185 page->CheckAndMarkPointer(visitor, address); | 187 page->CheckAndMarkPointer(visitor, address); |
| 186 return address; | 188 return address; |
| 187 } | 189 } |
| 188 | 190 |
| 189 #if !DCHECK_IS_ON() | 191 #if !DCHECK_IS_ON() |
| 190 heap_does_not_contain_cache_->AddEntry(address); | 192 heap_does_not_contain_cache_->AddEntry(address); |
| 191 #else | 193 #else |
| 192 if (!heap_does_not_contain_cache_->Lookup(address)) | 194 if (!heap_does_not_contain_cache_->Lookup(address)) |
| 193 heap_does_not_contain_cache_->AddEntry(address); | 195 heap_does_not_contain_cache_->AddEntry(address); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 212 page->CheckAndMarkPointer(visitor, address, callback); | 214 page->CheckAndMarkPointer(visitor, address, callback); |
| 213 return address; | 215 return address; |
| 214 } | 216 } |
| 215 if (!heap_does_not_contain_cache_->Lookup(address)) | 217 if (!heap_does_not_contain_cache_->Lookup(address)) |
| 216 heap_does_not_contain_cache_->AddEntry(address); | 218 heap_does_not_contain_cache_->AddEntry(address); |
| 217 return nullptr; | 219 return nullptr; |
| 218 } | 220 } |
| 219 #endif | 221 #endif |
| 220 | 222 |
| 221 void ThreadHeap::PushTraceCallback(void* object, TraceCallback callback) { | 223 void ThreadHeap::PushTraceCallback(void* object, TraceCallback callback) { |
| 222 ASSERT(ThreadState::Current()->IsInGC()); | 224 DCHECK(ThreadState::Current()->IsInGC()); |
| 223 | 225 |
| 224 CallbackStack::Item* slot = marking_stack_->AllocateEntry(); | 226 CallbackStack::Item* slot = marking_stack_->AllocateEntry(); |
| 225 *slot = CallbackStack::Item(object, callback); | 227 *slot = CallbackStack::Item(object, callback); |
| 226 } | 228 } |
| 227 | 229 |
| 228 bool ThreadHeap::PopAndInvokeTraceCallback(Visitor* visitor) { | 230 bool ThreadHeap::PopAndInvokeTraceCallback(Visitor* visitor) { |
| 229 CallbackStack::Item* item = marking_stack_->Pop(); | 231 CallbackStack::Item* item = marking_stack_->Pop(); |
| 230 if (!item) | 232 if (!item) |
| 231 return false; | 233 return false; |
| 232 item->Call(visitor); | 234 item->Call(visitor); |
| 233 return true; | 235 return true; |
| 234 } | 236 } |
| 235 | 237 |
| 236 void ThreadHeap::PushPostMarkingCallback(void* object, TraceCallback callback) { | 238 void ThreadHeap::PushPostMarkingCallback(void* object, TraceCallback callback) { |
| 237 ASSERT(ThreadState::Current()->IsInGC()); | 239 DCHECK(ThreadState::Current()->IsInGC()); |
| 238 | 240 |
| 239 CallbackStack::Item* slot = post_marking_callback_stack_->AllocateEntry(); | 241 CallbackStack::Item* slot = post_marking_callback_stack_->AllocateEntry(); |
| 240 *slot = CallbackStack::Item(object, callback); | 242 *slot = CallbackStack::Item(object, callback); |
| 241 } | 243 } |
| 242 | 244 |
| 243 bool ThreadHeap::PopAndInvokePostMarkingCallback(Visitor* visitor) { | 245 bool ThreadHeap::PopAndInvokePostMarkingCallback(Visitor* visitor) { |
| 244 if (CallbackStack::Item* item = post_marking_callback_stack_->Pop()) { | 246 if (CallbackStack::Item* item = post_marking_callback_stack_->Pop()) { |
| 245 item->Call(visitor); | 247 item->Call(visitor); |
| 246 return true; | 248 return true; |
| 247 } | 249 } |
| 248 return false; | 250 return false; |
| 249 } | 251 } |
| 250 | 252 |
| 251 void ThreadHeap::PushWeakCallback(void* closure, WeakCallback callback) { | 253 void ThreadHeap::PushWeakCallback(void* closure, WeakCallback callback) { |
| 252 ASSERT(ThreadState::Current()->IsInGC()); | 254 DCHECK(ThreadState::Current()->IsInGC()); |
| 253 | 255 |
| 254 CallbackStack::Item* slot = weak_callback_stack_->AllocateEntry(); | 256 CallbackStack::Item* slot = weak_callback_stack_->AllocateEntry(); |
| 255 *slot = CallbackStack::Item(closure, callback); | 257 *slot = CallbackStack::Item(closure, callback); |
| 256 } | 258 } |
| 257 | 259 |
| 258 bool ThreadHeap::PopAndInvokeWeakCallback(Visitor* visitor) { | 260 bool ThreadHeap::PopAndInvokeWeakCallback(Visitor* visitor) { |
| 259 if (CallbackStack::Item* item = weak_callback_stack_->Pop()) { | 261 if (CallbackStack::Item* item = weak_callback_stack_->Pop()) { |
| 260 item->Call(visitor); | 262 item->Call(visitor); |
| 261 return true; | 263 return true; |
| 262 } | 264 } |
| 263 return false; | 265 return false; |
| 264 } | 266 } |
| 265 | 267 |
| 266 void ThreadHeap::RegisterWeakTable(void* table, | 268 void ThreadHeap::RegisterWeakTable(void* table, |
| 267 EphemeronCallback iteration_callback, | 269 EphemeronCallback iteration_callback, |
| 268 EphemeronCallback iteration_done_callback) { | 270 EphemeronCallback iteration_done_callback) { |
| 269 ASSERT(ThreadState::Current()->IsInGC()); | 271 DCHECK(ThreadState::Current()->IsInGC()); |
| 270 | 272 |
| 271 CallbackStack::Item* slot = ephemeron_stack_->AllocateEntry(); | 273 CallbackStack::Item* slot = ephemeron_stack_->AllocateEntry(); |
| 272 *slot = CallbackStack::Item(table, iteration_callback); | 274 *slot = CallbackStack::Item(table, iteration_callback); |
| 273 | 275 |
| 274 // Register a post-marking callback to tell the tables that | 276 // Register a post-marking callback to tell the tables that |
| 275 // ephemeron iteration is complete. | 277 // ephemeron iteration is complete. |
| 276 PushPostMarkingCallback(table, iteration_done_callback); | 278 PushPostMarkingCallback(table, iteration_done_callback); |
| 277 } | 279 } |
| 278 | 280 |
| 279 #if DCHECK_IS_ON() | 281 #if DCHECK_IS_ON() |
| 280 bool ThreadHeap::WeakTableRegistered(const void* table) { | 282 bool ThreadHeap::WeakTableRegistered(const void* table) { |
| 281 ASSERT(ephemeron_stack_); | 283 DCHECK(ephemeron_stack_); |
| 282 return ephemeron_stack_->HasCallbackForObject(table); | 284 return ephemeron_stack_->HasCallbackForObject(table); |
| 283 } | 285 } |
| 284 #endif | 286 #endif |
| 285 | 287 |
| 286 void ThreadHeap::CommitCallbackStacks() { | 288 void ThreadHeap::CommitCallbackStacks() { |
| 287 marking_stack_->Commit(); | 289 marking_stack_->Commit(); |
| 288 post_marking_callback_stack_->Commit(); | 290 post_marking_callback_stack_->Commit(); |
| 289 weak_callback_stack_->Commit(); | 291 weak_callback_stack_->Commit(); |
| 290 ephemeron_stack_->Commit(); | 292 ephemeron_stack_->Commit(); |
| 291 } | 293 } |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 345 // 1. the ephemeronIterationDone callbacks on weak tables to do cleanup | 347 // 1. the ephemeronIterationDone callbacks on weak tables to do cleanup |
| 346 // (specifically to clear the queued bits for weak hash tables), and | 348 // (specifically to clear the queued bits for weak hash tables), and |
| 347 // 2. the markNoTracing callbacks on collection backings to mark them | 349 // 2. the markNoTracing callbacks on collection backings to mark them |
| 348 // if they are only reachable from their front objects. | 350 // if they are only reachable from their front objects. |
| 349 while (PopAndInvokePostMarkingCallback(visitor)) { | 351 while (PopAndInvokePostMarkingCallback(visitor)) { |
| 350 } | 352 } |
| 351 | 353 |
| 352 // Post-marking callbacks should not trace any objects and | 354 // Post-marking callbacks should not trace any objects and |
| 353 // therefore the marking stack should be empty after the | 355 // therefore the marking stack should be empty after the |
| 354 // post-marking callbacks. | 356 // post-marking callbacks. |
| 355 ASSERT(marking_stack_->IsEmpty()); | 357 DCHECK(marking_stack_->IsEmpty()); |
| 356 } | 358 } |
| 357 | 359 |
| 358 void ThreadHeap::WeakProcessing(Visitor* visitor) { | 360 void ThreadHeap::WeakProcessing(Visitor* visitor) { |
| 359 TRACE_EVENT0("blink_gc", "ThreadHeap::weakProcessing"); | 361 TRACE_EVENT0("blink_gc", "ThreadHeap::weakProcessing"); |
| 360 double start_time = WTF::CurrentTimeMS(); | 362 double start_time = WTF::CurrentTimeMS(); |
| 361 | 363 |
| 362 // Weak processing may access unmarked objects but are forbidden from | 364 // Weak processing may access unmarked objects but are forbidden from |
| 363 // ressurecting them. | 365 // ressurecting them. |
| 364 ThreadState::ObjectResurrectionForbiddenScope object_resurrection_forbidden( | 366 ThreadState::ObjectResurrectionForbiddenScope object_resurrection_forbidden( |
| 365 ThreadState::Current()); | 367 ThreadState::Current()); |
| 366 | 368 |
| 367 // Call weak callbacks on objects that may now be pointing to dead objects. | 369 // Call weak callbacks on objects that may now be pointing to dead objects. |
| 368 while (PopAndInvokeWeakCallback(visitor)) { | 370 while (PopAndInvokeWeakCallback(visitor)) { |
| 369 } | 371 } |
| 370 | 372 |
| 371 // It is not permitted to trace pointers of live objects in the weak | 373 // It is not permitted to trace pointers of live objects in the weak |
| 372 // callback phase, so the marking stack should still be empty here. | 374 // callback phase, so the marking stack should still be empty here. |
| 373 ASSERT(marking_stack_->IsEmpty()); | 375 DCHECK(marking_stack_->IsEmpty()); |
| 374 | 376 |
| 375 double time_for_weak_processing = WTF::CurrentTimeMS() - start_time; | 377 double time_for_weak_processing = WTF::CurrentTimeMS() - start_time; |
| 376 DEFINE_THREAD_SAFE_STATIC_LOCAL( | 378 DEFINE_THREAD_SAFE_STATIC_LOCAL( |
| 377 CustomCountHistogram, weak_processing_time_histogram, | 379 CustomCountHistogram, weak_processing_time_histogram, |
| 378 new CustomCountHistogram("BlinkGC.TimeForGlobalWeakProcessing", 1, | 380 new CustomCountHistogram("BlinkGC.TimeForGlobalWeakProcessing", 1, |
| 379 10 * 1000, 50)); | 381 10 * 1000, 50)); |
| 380 weak_processing_time_histogram.Count(time_for_weak_processing); | 382 weak_processing_time_histogram.Count(time_for_weak_processing); |
| 381 } | 383 } |
| 382 | 384 |
| 383 void ThreadHeap::ReportMemoryUsageHistogram() { | 385 void ThreadHeap::ReportMemoryUsageHistogram() { |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 474 size_t object_payload_size = 0; | 476 size_t object_payload_size = 0; |
| 475 thread_state_->SetGCState(ThreadState::kGCRunning); | 477 thread_state_->SetGCState(ThreadState::kGCRunning); |
| 476 thread_state_->MakeConsistentForGC(); | 478 thread_state_->MakeConsistentForGC(); |
| 477 object_payload_size += thread_state_->ObjectPayloadSizeForTesting(); | 479 object_payload_size += thread_state_->ObjectPayloadSizeForTesting(); |
| 478 thread_state_->SetGCState(ThreadState::kSweeping); | 480 thread_state_->SetGCState(ThreadState::kSweeping); |
| 479 thread_state_->SetGCState(ThreadState::kNoGCScheduled); | 481 thread_state_->SetGCState(ThreadState::kNoGCScheduled); |
| 480 return object_payload_size; | 482 return object_payload_size; |
| 481 } | 483 } |
| 482 | 484 |
| 483 void ThreadHeap::VisitPersistentRoots(Visitor* visitor) { | 485 void ThreadHeap::VisitPersistentRoots(Visitor* visitor) { |
| 484 ASSERT(ThreadState::Current()->IsInGC()); | 486 DCHECK(ThreadState::Current()->IsInGC()); |
| 485 TRACE_EVENT0("blink_gc", "ThreadHeap::visitPersistentRoots"); | 487 TRACE_EVENT0("blink_gc", "ThreadHeap::visitPersistentRoots"); |
| 486 ProcessHeap::GetCrossThreadPersistentRegion().TracePersistentNodes(visitor); | 488 ProcessHeap::GetCrossThreadPersistentRegion().TracePersistentNodes(visitor); |
| 487 | 489 |
| 488 thread_state_->VisitPersistents(visitor); | 490 thread_state_->VisitPersistents(visitor); |
| 489 } | 491 } |
| 490 | 492 |
| 491 void ThreadHeap::VisitStackRoots(Visitor* visitor) { | 493 void ThreadHeap::VisitStackRoots(Visitor* visitor) { |
| 492 ASSERT(ThreadState::Current()->IsInGC()); | 494 DCHECK(ThreadState::Current()->IsInGC()); |
| 493 TRACE_EVENT0("blink_gc", "ThreadHeap::visitStackRoots"); | 495 TRACE_EVENT0("blink_gc", "ThreadHeap::visitStackRoots"); |
| 494 thread_state_->VisitStack(visitor); | 496 thread_state_->VisitStack(visitor); |
| 495 } | 497 } |
| 496 | 498 |
| 497 BasePage* ThreadHeap::LookupPageForAddress(Address address) { | 499 BasePage* ThreadHeap::LookupPageForAddress(Address address) { |
| 498 ASSERT(ThreadState::Current()->IsInGC()); | 500 DCHECK(ThreadState::Current()->IsInGC()); |
| 499 if (PageMemoryRegion* region = region_tree_->Lookup(address)) { | 501 if (PageMemoryRegion* region = region_tree_->Lookup(address)) { |
| 500 return region->PageFromAddress(address); | 502 return region->PageFromAddress(address); |
| 501 } | 503 } |
| 502 return nullptr; | 504 return nullptr; |
| 503 } | 505 } |
| 504 | 506 |
| 505 void ThreadHeap::ResetHeapCounters() { | 507 void ThreadHeap::ResetHeapCounters() { |
| 506 ASSERT(ThreadState::Current()->IsInGC()); | 508 DCHECK(ThreadState::Current()->IsInGC()); |
| 507 | 509 |
| 508 ThreadHeap::ReportMemoryUsageForTracing(); | 510 ThreadHeap::ReportMemoryUsageForTracing(); |
| 509 | 511 |
| 510 ProcessHeap::DecreaseTotalAllocatedObjectSize(stats_.AllocatedObjectSize()); | 512 ProcessHeap::DecreaseTotalAllocatedObjectSize(stats_.AllocatedObjectSize()); |
| 511 ProcessHeap::DecreaseTotalMarkedObjectSize(stats_.MarkedObjectSize()); | 513 ProcessHeap::DecreaseTotalMarkedObjectSize(stats_.MarkedObjectSize()); |
| 512 | 514 |
| 513 stats_.Reset(); | 515 stats_.Reset(); |
| 514 thread_state_->ResetHeapCounters(); | 516 thread_state_->ResetHeapCounters(); |
| 515 } | 517 } |
| 516 | 518 |
| 517 ThreadHeap* ThreadHeap::main_thread_heap_ = nullptr; | 519 ThreadHeap* ThreadHeap::main_thread_heap_ = nullptr; |
| 518 | 520 |
| 519 } // namespace blink | 521 } // namespace blink |
| OLD | NEW |