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 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
320 if (!state->isAtSafePoint()) | 320 if (!state->isAtSafePoint()) |
321 state->enterSafePointWithoutPointers(); | 321 state->enterSafePointWithoutPointers(); |
322 MutexLocker locker(threadAttachMutex()); | 322 MutexLocker locker(threadAttachMutex()); |
323 state->leaveSafePoint(); | 323 state->leaveSafePoint(); |
324 attachedThreads().remove(state); | 324 attachedThreads().remove(state); |
325 delete state; | 325 delete state; |
326 } | 326 } |
327 | 327 |
328 void ThreadState::visitRoots(Visitor* visitor) | 328 void ThreadState::visitRoots(Visitor* visitor) |
329 { | 329 { |
330 { | |
331 // All threads are at safepoints so this is not strictly necessary. | |
332 // However we acquire the mutex to make mutation and traversal of this | |
333 // list symmetrical. | |
334 MutexLocker locker(globalRootsMutex()); | |
335 globalRoots()->trace(visitor); | |
336 } | |
337 | |
330 AttachedThreadStateSet& threads = attachedThreads(); | 338 AttachedThreadStateSet& threads = attachedThreads(); |
331 for (AttachedThreadStateSet::iterator it = threads.begin(), end = threads.en d(); it != end; ++it) | 339 for (AttachedThreadStateSet::iterator it = threads.begin(), end = threads.en d(); it != end; ++it) |
332 (*it)->trace(visitor); | 340 (*it)->trace(visitor); |
333 } | 341 } |
334 | 342 |
335 NO_SANITIZE_ADDRESS | 343 NO_SANITIZE_ADDRESS |
336 void ThreadState::visitStack(Visitor* visitor) | 344 void ThreadState::visitStack(Visitor* visitor) |
337 { | 345 { |
338 Address* start = reinterpret_cast<Address*>(m_startOfStack); | 346 Address* start = reinterpret_cast<Address*>(m_startOfStack); |
339 // If there is a safepoint scope marker we should stop the stack | 347 // If there is a safepoint scope marker we should stop the stack |
340 // scanning there to not touch active parts of the stack. Anything | 348 // scanning there to not touch active parts of the stack. Anything |
341 // interesting beyond that point is in the safepoint stack copy. | 349 // interesting beyond that point is in the safepoint stack copy. |
342 // If there is no scope marker the thread is blocked and we should | 350 // If there is no scope marker the thread is blocked and we should |
343 // scan all the way to the recorded end stack pointer. | 351 // scan all the way to the recorded end stack pointer. |
344 Address* end = reinterpret_cast<Address*>(m_endOfStack); | 352 Address* end = reinterpret_cast<Address*>(m_endOfStack); |
345 Address* safePointScopeMarker = reinterpret_cast<Address*>(m_safePointScopeM arker); | 353 Address* safePointScopeMarker = reinterpret_cast<Address*>(m_safePointScopeM arker); |
346 Address* current = safePointScopeMarker ? safePointScopeMarker : end; | 354 Address* current = safePointScopeMarker ? safePointScopeMarker : end; |
347 | 355 |
348 // Ensure that current is aligned by address size otherwise the loop below | 356 // Ensure that current is aligned by address size otherwise the loop below |
349 // will read past start address. | 357 // will read past start address. |
350 current = reinterpret_cast<Address*>(reinterpret_cast<intptr_t>(current) & ~ (sizeof(Address) - 1)); | 358 current = reinterpret_cast<Address*>(reinterpret_cast<intptr_t>(current) & ~ (sizeof(Address) - 1)); |
351 | 359 |
352 for (; current < start; ++current) | 360 for (; current < start; ++current) |
353 Heap::checkAndMarkPointer(visitor, *current); | 361 Heap::checkAndMarkPointer(visitor, *current); |
354 | 362 |
355 for (Vector<Address>::iterator it = m_safePointStackCopy.begin(); it != m_sa fePointStackCopy.end(); ++it) | 363 for (Vector<Address>::iterator it = m_safePointStackCopy.begin(); it != m_sa fePointStackCopy.end(); ++it) |
356 Heap::checkAndMarkPointer(visitor, *it); | 364 Heap::checkAndMarkPointer(visitor, *it); |
357 } | 365 } |
358 | 366 |
359 void ThreadState::visitPersistents(Visitor* visitor) | 367 void ThreadState::visitPersistents(Visitor* visitor) |
haraken
2014/02/18 01:35:12
I sometimes find it confusing that we have visitPe
| |
360 { | 368 { |
361 for (PersistentNode* current = m_persistents->m_next; current != m_persisten ts; current = current->m_next) { | 369 m_persistents->trace(visitor); |
362 current->trace(visitor); | |
363 } | |
364 } | 370 } |
365 | 371 |
366 void ThreadState::trace(Visitor* visitor) | 372 void ThreadState::trace(Visitor* visitor) |
367 { | 373 { |
368 if (m_stackState == HeapPointersOnStack) | 374 if (m_stackState == HeapPointersOnStack) |
369 visitStack(visitor); | 375 visitStack(visitor); |
370 visitPersistents(visitor); | 376 visitPersistents(visitor); |
371 } | 377 } |
372 | 378 |
373 bool ThreadState::checkAndMarkPointer(Visitor* visitor, Address address) | 379 bool ThreadState::checkAndMarkPointer(Visitor* visitor, Address address) |
374 { | 380 { |
375 // If thread is cleaning up ignore conservative pointers. | 381 // If thread is cleaning up ignore conservative pointers. |
376 if (m_isCleaningUp) | 382 if (m_isCleaningUp) |
377 return false; | 383 return false; |
378 | 384 |
379 BaseHeapPage* page = heapPageFromAddress(address); | 385 BaseHeapPage* page = heapPageFromAddress(address); |
380 if (page) | 386 if (page) |
381 return page->checkAndMarkPointer(visitor, address); | 387 return page->checkAndMarkPointer(visitor, address); |
382 // Not in heap pages, check large objects | 388 // Not in heap pages, check large objects |
383 for (int i = 0; i < NumberOfHeaps; i++) { | 389 for (int i = 0; i < NumberOfHeaps; i++) { |
384 if (m_heaps[i]->checkAndMarkLargeHeapObject(visitor, address)) | 390 if (m_heaps[i]->checkAndMarkLargeHeapObject(visitor, address)) |
385 return true; | 391 return true; |
386 } | 392 } |
387 return false; | 393 return false; |
388 } | 394 } |
389 | 395 |
396 PersistentNode* ThreadState::globalRoots() | |
397 { | |
398 AtomicallyInitializedStatic(PersistentNode*, anchor = new PersistentAnchor); | |
399 return anchor; | |
400 } | |
401 | |
402 Mutex& ThreadState::globalRootsMutex() | |
403 { | |
404 AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex); | |
405 return mutex; | |
406 } | |
407 | |
390 // Trigger garbage collection on a 50% increase in size, but not for | 408 // Trigger garbage collection on a 50% increase in size, but not for |
391 // less than 2 pages. | 409 // less than 2 pages. |
392 static bool increasedEnoughToGC(size_t newSize, size_t oldSize) | 410 static bool increasedEnoughToGC(size_t newSize, size_t oldSize) |
393 { | 411 { |
394 if (newSize < 2 * blinkPagePayloadSize()) | 412 if (newSize < 2 * blinkPagePayloadSize()) |
395 return false; | 413 return false; |
396 return newSize > oldSize + (oldSize >> 1); | 414 return newSize > oldSize + (oldSize >> 1); |
397 } | 415 } |
398 | 416 |
399 // FIXME: The heuristics are local for a thread at this | 417 // FIXME: The heuristics are local for a thread at this |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
678 state->safePoint(HeapPointersOnStack); | 696 state->safePoint(HeapPointersOnStack); |
679 } | 697 } |
680 | 698 |
681 ThreadState::AttachedThreadStateSet& ThreadState::attachedThreads() | 699 ThreadState::AttachedThreadStateSet& ThreadState::attachedThreads() |
682 { | 700 { |
683 DEFINE_STATIC_LOCAL(AttachedThreadStateSet, threads, ()); | 701 DEFINE_STATIC_LOCAL(AttachedThreadStateSet, threads, ()); |
684 return threads; | 702 return threads; |
685 } | 703 } |
686 | 704 |
687 } | 705 } |
OLD | NEW |