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 |