Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(30)

Unified Diff: sky/engine/platform/heap/ThreadState.cpp

Issue 681963002: Remove heap/*.cpp files (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « sky/engine/platform/heap/ThreadState.h ('k') | sky/engine/platform/heap/Visitor.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sky/engine/platform/heap/ThreadState.cpp
diff --git a/sky/engine/platform/heap/ThreadState.cpp b/sky/engine/platform/heap/ThreadState.cpp
deleted file mode 100644
index 39bff37faef35a0d76f416afc52b6b52530b4e12..0000000000000000000000000000000000000000
--- a/sky/engine/platform/heap/ThreadState.cpp
+++ /dev/null
@@ -1,898 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "platform/heap/ThreadState.h"
-
-#include "platform/ScriptForbiddenScope.h"
-#include "platform/TraceEvent.h"
-#include "platform/heap/AddressSanitizer.h"
-#include "platform/heap/Handle.h"
-#include "platform/heap/Heap.h"
-#include "public/platform/Platform.h"
-#include "public/platform/WebThread.h"
-#include "wtf/ThreadingPrimitives.h"
-#if ENABLE(GC_PROFILE_HEAP)
-#include "platform/TracedValue.h"
-#endif
-
-#if defined(__GLIBC__)
-extern "C" void* __libc_stack_end; // NOLINT
-#endif
-
-#if defined(MEMORY_SANITIZER)
-#include <sanitizer/msan_interface.h>
-#endif
-
-namespace blink {
-
-static void* getStackStart()
-{
-#if defined(__GLIBC__) || OS(ANDROID)
- pthread_attr_t attr;
- if (!pthread_getattr_np(pthread_self(), &attr)) {
- void* base;
- size_t size;
- int error = pthread_attr_getstack(&attr, &base, &size);
- RELEASE_ASSERT(!error);
- pthread_attr_destroy(&attr);
- return reinterpret_cast<Address>(base) + size;
- }
-#if defined(__GLIBC__)
- // pthread_getattr_np can fail for the main thread. In this case
- // just like NaCl we rely on the __libc_stack_end to give us
- // the start of the stack.
- // See https://code.google.com/p/nativeclient/issues/detail?id=3431.
- return __libc_stack_end;
-#else
- ASSERT_NOT_REACHED();
- return 0;
-#endif
-#elif OS(MACOSX)
- return pthread_get_stackaddr_np(pthread_self());
-#else
-#error Unsupported getStackStart on this platform.
-#endif
-}
-
-WTF::ThreadSpecific<ThreadState*>* ThreadState::s_threadSpecific = 0;
-uint8_t ThreadState::s_mainThreadStateStorage[sizeof(ThreadState)];
-SafePointBarrier* ThreadState::s_safePointBarrier = 0;
-bool ThreadState::s_inGC = false;
-
-static Mutex& threadAttachMutex()
-{
- AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex);
- return mutex;
-}
-
-class SafePointBarrier {
-public:
- SafePointBarrier() : m_canResume(1), m_unparkedThreadCount(0) { }
- ~SafePointBarrier() { }
-
- // Request other attached threads that are not at safe points to park themselves on safepoints.
- bool parkOthers()
- {
- return true;
- }
-
- void resumeOthers(bool barrierLocked = false)
- {
- }
-
- void checkAndPark(ThreadState* state, SafePointAwareMutexLocker* locker = 0)
- {
- }
-
- void enterSafePoint(ThreadState* state)
- {
- }
-
- void leaveSafePoint(ThreadState* state, SafePointAwareMutexLocker* locker = 0)
- {
- }
-
-private:
- void doPark(ThreadState* state, intptr_t* stackEnd)
- {
- state->recordStackEnd(stackEnd);
- MutexLocker locker(m_mutex);
- if (!atomicDecrement(&m_unparkedThreadCount))
- m_parked.signal();
- while (!acquireLoad(&m_canResume))
- m_resume.wait(m_mutex);
- atomicIncrement(&m_unparkedThreadCount);
- }
-
- static void parkAfterPushRegisters(SafePointBarrier* barrier, ThreadState* state, intptr_t* stackEnd)
- {
- barrier->doPark(state, stackEnd);
- }
-
- void doEnterSafePoint(ThreadState* state, intptr_t* stackEnd)
- {
- state->recordStackEnd(stackEnd);
- state->copyStackUntilSafePointScope();
- // m_unparkedThreadCount tracks amount of unparked threads. It is
- // positive if and only if we have requested other threads to park
- // at safe-points in preparation for GC. The last thread to park
- // itself will make the counter hit zero and should notify GC thread
- // that it is safe to proceed.
- // If no other thread is waiting for other threads to park then
- // this counter can be negative: if N threads are at safe-points
- // the counter will be -N.
- if (!atomicDecrement(&m_unparkedThreadCount)) {
- MutexLocker locker(m_mutex);
- m_parked.signal(); // Safe point reached.
- }
- }
-
- static void enterSafePointAfterPushRegisters(SafePointBarrier* barrier, ThreadState* state, intptr_t* stackEnd)
- {
- barrier->doEnterSafePoint(state, stackEnd);
- }
-
- volatile int m_canResume;
- volatile int m_unparkedThreadCount;
- Mutex m_mutex;
- ThreadCondition m_parked;
- ThreadCondition m_resume;
-};
-
-BaseHeapPage::BaseHeapPage(PageMemory* storage, const GCInfo* gcInfo, ThreadState* state)
- : m_storage(storage)
- , m_gcInfo(gcInfo)
- , m_threadState(state)
- , m_terminating(false)
- , m_tracedAfterOrphaned(false)
-{
- ASSERT(isPageHeaderAddress(reinterpret_cast<Address>(this)));
-}
-
-// Statically unfold the heap initialization loop so the compiler statically
-// knows the heap index when using HeapIndexTrait.
-template<int num> struct InitializeHeaps {
- static const int index = num - 1;
- static void init(BaseHeap** heaps, ThreadState* state)
- {
- InitializeHeaps<index>::init(heaps, state);
- heaps[index] = new typename HeapIndexTrait<index>::HeapType(state, index);
- }
-};
-template<> struct InitializeHeaps<0> {
- static void init(BaseHeap** heaps, ThreadState* state) { }
-};
-
-ThreadState::ThreadState()
- : m_thread(currentThread())
- , m_persistents(adoptPtr(new PersistentAnchor()))
- , m_startOfStack(reinterpret_cast<intptr_t*>(getStackStart()))
- , m_endOfStack(reinterpret_cast<intptr_t*>(getStackStart()))
- , m_safePointScopeMarker(0)
- , m_atSafePoint(false)
- , m_interruptors()
- , m_gcRequested(false)
- , m_forcePreciseGCForTesting(false)
- , m_sweepRequested(0)
- , m_sweepInProgress(false)
- , m_noAllocationCount(0)
- , m_inGC(false)
- , m_heapContainsCache(adoptPtr(new HeapContainsCache()))
- , m_isTerminating(false)
- , m_lowCollectionRate(false)
- , m_numberOfSweeperTasks(0)
-#if defined(ADDRESS_SANITIZER)
- , m_asanFakeStack(__asan_get_current_fake_stack())
-#endif
-{
- ASSERT(!**s_threadSpecific);
- **s_threadSpecific = this;
-
- InitializeHeaps<NumberOfHeaps>::init(m_heaps, this);
-
- CallbackStack::init(&m_weakCallbackStack);
-}
-
-ThreadState::~ThreadState()
-{
- checkThread();
- CallbackStack::shutdown(&m_weakCallbackStack);
- for (int i = 0; i < NumberOfHeaps; i++)
- delete m_heaps[i];
- deleteAllValues(m_interruptors);
- **s_threadSpecific = 0;
-}
-
-void ThreadState::attach()
-{
- RELEASE_ASSERT(!Heap::s_shutdownCalled);
- MutexLocker locker(threadAttachMutex());
- ThreadState* state = new ThreadState();
- attachedThreads().add(state);
-}
-
-void ThreadState::cleanupPages()
-{
- for (int i = 0; i < NumberOfHeaps; ++i)
- m_heaps[i]->cleanupPages();
-}
-
-void ThreadState::cleanup()
-{
- for (size_t i = 0; i < m_cleanupTasks.size(); i++)
- m_cleanupTasks[i]->preCleanup();
-
- {
- // Grab the threadAttachMutex to ensure only one thread can shutdown at
- // a time and that no other thread can do a global GC. It also allows
- // safe iteration of the attachedThreads set which happens as part of
- // thread local GC asserts. We enter a safepoint while waiting for the
- // lock to avoid a dead-lock where another thread has already requested
- // GC.
- SafePointAwareMutexLocker locker(threadAttachMutex(), NoHeapPointersOnStack);
-
- // From here on ignore all conservatively discovered
- // pointers into the heap owned by this thread.
- m_isTerminating = true;
-
- // Set the terminate flag on all heap pages of this thread. This is used to
- // ensure we don't trace pages on other threads that are not part of the
- // thread local GC.
- setupHeapsForTermination();
-
- // Do thread local GC's as long as the count of thread local Persistents
- // changes and is above zero.
- PersistentAnchor* anchor = static_cast<PersistentAnchor*>(m_persistents.get());
- int oldCount = -1;
- int currentCount = anchor->numberOfPersistents();
- ASSERT(currentCount >= 0);
- while (currentCount != oldCount) {
- Heap::collectGarbageForTerminatingThread(this);
- oldCount = currentCount;
- currentCount = anchor->numberOfPersistents();
- }
- // We should not have any persistents left when getting to this point,
- // if we have it is probably a bug so adding a debug ASSERT to catch this.
- ASSERT(!currentCount);
-
- // Add pages to the orphaned page pool to ensure any global GCs from this point
- // on will not trace objects on this thread's heaps.
- cleanupPages();
-
- ASSERT(attachedThreads().contains(this));
- attachedThreads().remove(this);
- }
-
- for (size_t i = 0; i < m_cleanupTasks.size(); i++)
- m_cleanupTasks[i]->postCleanup();
- m_cleanupTasks.clear();
-}
-
-
-void ThreadState::visitPersistentRoots(Visitor* visitor)
-{
- {
- // All threads are at safepoints so this is not strictly necessary.
- // However we acquire the mutex to make mutation and traversal of this
- // list symmetrical.
- MutexLocker locker(globalRootsMutex());
- globalRoots()->trace(visitor);
- }
-
- AttachedThreadStateSet& threads = attachedThreads();
- for (AttachedThreadStateSet::iterator it = threads.begin(), end = threads.end(); it != end; ++it)
- (*it)->visitPersistents(visitor);
-}
-
-void ThreadState::visitStackRoots(Visitor* visitor)
-{
- AttachedThreadStateSet& threads = attachedThreads();
- for (AttachedThreadStateSet::iterator it = threads.begin(), end = threads.end(); it != end; ++it)
- (*it)->visitStack(visitor);
-}
-
-NO_SANITIZE_ADDRESS
-void ThreadState::visitAsanFakeStackForPointer(Visitor* visitor, Address ptr)
-{
-#if defined(ADDRESS_SANITIZER)
- Address* start = reinterpret_cast<Address*>(m_startOfStack);
- Address* end = reinterpret_cast<Address*>(m_endOfStack);
- Address* fakeFrameStart = 0;
- Address* fakeFrameEnd = 0;
- Address* maybeFakeFrame = reinterpret_cast<Address*>(ptr);
- Address* realFrameForFakeFrame =
- reinterpret_cast<Address*>(
- __asan_addr_is_in_fake_stack(
- m_asanFakeStack, maybeFakeFrame,
- reinterpret_cast<void**>(&fakeFrameStart),
- reinterpret_cast<void**>(&fakeFrameEnd)));
- if (realFrameForFakeFrame) {
- // This is a fake frame from the asan fake stack.
- if (realFrameForFakeFrame > end && start > realFrameForFakeFrame) {
- // The real stack address for the asan fake frame is
- // within the stack range that we need to scan so we need
- // to visit the values in the fake frame.
- for (Address* p = fakeFrameStart; p < fakeFrameEnd; p++)
- Heap::checkAndMarkPointer(visitor, *p);
- }
- }
-#endif
-}
-
-NO_SANITIZE_ADDRESS
-void ThreadState::visitStack(Visitor* visitor)
-{
- if (m_stackState == NoHeapPointersOnStack)
- return;
-
- Address* start = reinterpret_cast<Address*>(m_startOfStack);
- // If there is a safepoint scope marker we should stop the stack
- // scanning there to not touch active parts of the stack. Anything
- // interesting beyond that point is in the safepoint stack copy.
- // If there is no scope marker the thread is blocked and we should
- // scan all the way to the recorded end stack pointer.
- Address* end = reinterpret_cast<Address*>(m_endOfStack);
- Address* safePointScopeMarker = reinterpret_cast<Address*>(m_safePointScopeMarker);
- Address* current = safePointScopeMarker ? safePointScopeMarker : end;
-
- // Ensure that current is aligned by address size otherwise the loop below
- // will read past start address.
- current = reinterpret_cast<Address*>(reinterpret_cast<intptr_t>(current) & ~(sizeof(Address) - 1));
-
- for (; current < start; ++current) {
- Address ptr = *current;
-#if defined(MEMORY_SANITIZER)
- // |ptr| may be uninitialized by design. Mark it as initialized to keep
- // MSan from complaining.
- // Note: it may be tempting to get rid of |ptr| and simply use |current|
- // here, but that would be incorrect. We intentionally use a local
- // variable because we don't want to unpoison the original stack.
- __msan_unpoison(&ptr, sizeof(ptr));
-#endif
- Heap::checkAndMarkPointer(visitor, ptr);
- visitAsanFakeStackForPointer(visitor, ptr);
- }
-
- for (Vector<Address>::iterator it = m_safePointStackCopy.begin(); it != m_safePointStackCopy.end(); ++it) {
- Address ptr = *it;
-#if defined(MEMORY_SANITIZER)
- // See the comment above.
- __msan_unpoison(&ptr, sizeof(ptr));
-#endif
- Heap::checkAndMarkPointer(visitor, ptr);
- visitAsanFakeStackForPointer(visitor, ptr);
- }
-}
-
-void ThreadState::visitPersistents(Visitor* visitor)
-{
- m_persistents->trace(visitor);
-}
-
-bool ThreadState::checkAndMarkPointer(Visitor* visitor, Address address)
-{
- // If thread is terminating ignore conservative pointers.
- if (m_isTerminating)
- return false;
-
- // This checks for normal pages and for large objects which span the extent
- // of several normal pages.
- BaseHeapPage* page = heapPageFromAddress(address);
- if (page) {
- page->checkAndMarkPointer(visitor, address);
- // Whether or not the pointer was within an object it was certainly
- // within a page that is part of the heap, so we don't want to ask the
- // other other heaps or put this address in the
- // HeapDoesNotContainCache.
- return true;
- }
-
- return false;
-}
-
-#if ENABLE(GC_PROFILE_MARKING)
-const GCInfo* ThreadState::findGCInfo(Address address)
-{
- BaseHeapPage* page = heapPageFromAddress(address);
- if (page) {
- return page->findGCInfo(address);
- }
- return 0;
-}
-#endif
-
-#if ENABLE(GC_PROFILE_HEAP)
-size_t ThreadState::SnapshotInfo::getClassTag(const GCInfo* gcinfo)
-{
- HashMap<const GCInfo*, size_t>::AddResult result = classTags.add(gcinfo, classTags.size());
- if (result.isNewEntry) {
- liveCount.append(0);
- deadCount.append(0);
- liveSize.append(0);
- deadSize.append(0);
- generations.append(Vector<int, 8>());
- generations.last().fill(0, 8);
- }
- return result.storedValue->value;
-}
-
-void ThreadState::snapshot()
-{
- SnapshotInfo info(this);
- RefPtr<TracedValue> json = TracedValue::create();
-
-#define SNAPSHOT_HEAP(HeapType) \
- { \
- json->beginDictionary(); \
- json->setString("name", #HeapType); \
- m_heaps[HeapType##Heap]->snapshot(json.get(), &info); \
- json->endDictionary(); \
- json->beginDictionary(); \
- json->setString("name", #HeapType"NonFinalized"); \
- m_heaps[HeapType##HeapNonFinalized]->snapshot(json.get(), &info); \
- json->endDictionary(); \
- }
- json->beginArray("heaps");
- SNAPSHOT_HEAP(General);
- SNAPSHOT_HEAP(CollectionBacking);
- FOR_EACH_TYPED_HEAP(SNAPSHOT_HEAP);
- json->endArray();
-#undef SNAPSHOT_HEAP
-
- json->setInteger("allocatedSpace", m_stats.totalAllocatedSpace());
- json->setInteger("objectSpace", m_stats.totalObjectSpace());
- json->setInteger("pageCount", info.pageCount);
- json->setInteger("freeSize", info.freeSize);
-
- Vector<String> classNameVector(info.classTags.size());
- for (HashMap<const GCInfo*, size_t>::iterator it = info.classTags.begin(); it != info.classTags.end(); ++it)
- classNameVector[it->value] = it->key->m_className;
-
- size_t liveSize = 0;
- size_t deadSize = 0;
- json->beginArray("classes");
- for (size_t i = 0; i < classNameVector.size(); ++i) {
- json->beginDictionary();
- json->setString("name", classNameVector[i]);
- json->setInteger("liveCount", info.liveCount[i]);
- json->setInteger("deadCount", info.deadCount[i]);
- json->setInteger("liveSize", info.liveSize[i]);
- json->setInteger("deadSize", info.deadSize[i]);
- liveSize += info.liveSize[i];
- deadSize += info.deadSize[i];
-
- json->beginArray("generations");
- for (size_t j = 0; j < heapObjectGenerations; ++j)
- json->pushInteger(info.generations[i][j]);
- json->endArray();
- json->endDictionary();
- }
- json->endArray();
- json->setInteger("liveSize", liveSize);
- json->setInteger("deadSize", deadSize);
-
- TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID("blink_gc", "ThreadState", this, json.release());
-}
-#endif
-
-void ThreadState::pushWeakObjectPointerCallback(void* object, WeakPointerCallback callback)
-{
- CallbackStack::Item* slot = m_weakCallbackStack->allocateEntry(&m_weakCallbackStack);
- *slot = CallbackStack::Item(object, callback);
-}
-
-bool ThreadState::popAndInvokeWeakPointerCallback(Visitor* visitor)
-{
- return m_weakCallbackStack->popAndInvokeCallback<WeaknessProcessing>(&m_weakCallbackStack, visitor);
-}
-
-PersistentNode* ThreadState::globalRoots()
-{
- AtomicallyInitializedStatic(PersistentNode*, anchor = new PersistentAnchor);
- return anchor;
-}
-
-Mutex& ThreadState::globalRootsMutex()
-{
- AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex);
- return mutex;
-}
-
-// Trigger garbage collection on a 50% increase in size, but not for
-// less than 512kbytes.
-bool ThreadState::increasedEnoughToGC(size_t newSize, size_t oldSize)
-{
- if (newSize < 1 << 19)
- return false;
- size_t limit = oldSize + (oldSize >> 1);
- return newSize > limit;
-}
-
-// FIXME: The heuristics are local for a thread at this
-// point. Consider using heuristics that take memory for all threads
-// into account.
-bool ThreadState::shouldGC()
-{
- // Do not GC during sweeping. We allow allocation during
- // finalization, but those allocations are not allowed
- // to lead to nested garbage collections.
- return !m_sweepInProgress && increasedEnoughToGC(m_stats.totalObjectSpace(), m_statsAfterLastGC.totalObjectSpace());
-}
-
-// Trigger conservative garbage collection on a 100% increase in size,
-// but not for less than 4Mbytes. If the system currently has a low
-// collection rate, then require a 300% increase in size.
-bool ThreadState::increasedEnoughToForceConservativeGC(size_t newSize, size_t oldSize)
-{
- if (newSize < 1 << 22)
- return false;
- size_t limit = (m_lowCollectionRate ? 4 : 2) * oldSize;
- return newSize > limit;
-}
-
-// FIXME: The heuristics are local for a thread at this
-// point. Consider using heuristics that take memory for all threads
-// into account.
-bool ThreadState::shouldForceConservativeGC()
-{
- // Do not GC during sweeping. We allow allocation during
- // finalization, but those allocations are not allowed
- // to lead to nested garbage collections.
- return !m_sweepInProgress && increasedEnoughToForceConservativeGC(m_stats.totalObjectSpace(), m_statsAfterLastGC.totalObjectSpace());
-}
-
-bool ThreadState::sweepRequested()
-{
- ASSERT(isAnyThreadInGC() || checkThread());
- return m_sweepRequested;
-}
-
-void ThreadState::setSweepRequested()
-{
- // Sweep requested is set from the thread that initiates garbage
- // collection which could be different from the thread for this
- // thread state. Therefore the setting of m_sweepRequested needs a
- // barrier.
- atomicTestAndSetToOne(&m_sweepRequested);
-}
-
-void ThreadState::clearSweepRequested()
-{
- checkThread();
- m_sweepRequested = 0;
-}
-
-bool ThreadState::gcRequested()
-{
- checkThread();
- return m_gcRequested;
-}
-
-void ThreadState::setGCRequested()
-{
- checkThread();
- m_gcRequested = true;
-}
-
-void ThreadState::clearGCRequested()
-{
- checkThread();
- m_gcRequested = false;
-}
-
-void ThreadState::performPendingGC(StackState stackState)
-{
- if (stackState == NoHeapPointersOnStack) {
- if (forcePreciseGCForTesting()) {
- setForcePreciseGCForTesting(false);
- Heap::collectAllGarbage();
- } else if (gcRequested()) {
- Heap::collectGarbage(NoHeapPointersOnStack);
- }
- }
-}
-
-void ThreadState::setForcePreciseGCForTesting(bool value)
-{
- checkThread();
- m_forcePreciseGCForTesting = value;
-}
-
-bool ThreadState::forcePreciseGCForTesting()
-{
- checkThread();
- return m_forcePreciseGCForTesting;
-}
-
-void ThreadState::makeConsistentForSweeping()
-{
- for (int i = 0; i < NumberOfHeaps; i++)
- m_heaps[i]->makeConsistentForSweeping();
-}
-
-#if ENABLE(ASSERT)
-bool ThreadState::isConsistentForSweeping()
-{
- for (int i = 0; i < NumberOfHeaps; i++) {
- if (!m_heaps[i]->isConsistentForSweeping())
- return false;
- }
- return true;
-}
-#endif
-
-void ThreadState::prepareForGC()
-{
- for (int i = 0; i < NumberOfHeaps; i++) {
- BaseHeap* heap = m_heaps[i];
- heap->makeConsistentForSweeping();
- // If a new GC is requested before this thread got around to sweep, ie. due to the
- // thread doing a long running operation, we clear the mark bits and mark any of
- // the dead objects as dead. The latter is used to ensure the next GC marking does
- // not trace already dead objects. If we trace a dead object we could end up tracing
- // into garbage or the middle of another object via the newly conservatively found
- // object.
- if (sweepRequested())
- heap->clearLiveAndMarkDead();
- }
- setSweepRequested();
-}
-
-void ThreadState::setupHeapsForTermination()
-{
- for (int i = 0; i < NumberOfHeaps; i++)
- m_heaps[i]->prepareHeapForTermination();
-}
-
-BaseHeapPage* ThreadState::heapPageFromAddress(Address address)
-{
- BaseHeapPage* cachedPage = heapContainsCache()->lookup(address);
-#if !ENABLE(ASSERT)
- if (cachedPage)
- return cachedPage;
-#endif
-
- for (int i = 0; i < NumberOfHeaps; i++) {
- BaseHeapPage* page = m_heaps[i]->heapPageFromAddress(address);
- if (page) {
- // Asserts that make sure heapPageFromAddress takes addresses from
- // the whole aligned blinkPageSize memory area. This is necessary
- // for the negative cache to work.
- ASSERT(page->isLargeObject() || page == m_heaps[i]->heapPageFromAddress(roundToBlinkPageStart(address)));
- if (roundToBlinkPageStart(address) != roundToBlinkPageEnd(address))
- ASSERT(page->isLargeObject() || page == m_heaps[i]->heapPageFromAddress(roundToBlinkPageEnd(address) - 1));
- ASSERT(!cachedPage || page == cachedPage);
- if (!cachedPage)
- heapContainsCache()->addEntry(address, page);
- return page;
- }
- }
- ASSERT(!cachedPage);
- return 0;
-}
-
-void ThreadState::getStats(HeapStats& stats)
-{
- stats = m_stats;
-#if ENABLE(ASSERT)
- if (isConsistentForSweeping()) {
- HeapStats scannedStats;
- for (int i = 0; i < NumberOfHeaps; i++)
- m_heaps[i]->getScannedStats(scannedStats);
- ASSERT(scannedStats == stats);
- }
-#endif
-}
-
-bool ThreadState::stopThreads()
-{
- return s_safePointBarrier->parkOthers();
-}
-
-void ThreadState::resumeThreads()
-{
- s_safePointBarrier->resumeOthers();
-}
-
-void ThreadState::safePoint(StackState stackState)
-{
- checkThread();
- performPendingGC(stackState);
- ASSERT(!m_atSafePoint);
- m_stackState = stackState;
- m_atSafePoint = true;
- s_safePointBarrier->checkAndPark(this);
- m_atSafePoint = false;
- m_stackState = HeapPointersOnStack;
- performPendingSweep();
-}
-
-#ifdef ADDRESS_SANITIZER
-// When we are running under AddressSanitizer with detect_stack_use_after_return=1
-// then stack marker obtained from SafePointScope will point into a fake stack.
-// Detect this case by checking if it falls in between current stack frame
-// and stack start and use an arbitrary high enough value for it.
-// Don't adjust stack marker in any other case to match behavior of code running
-// without AddressSanitizer.
-NO_SANITIZE_ADDRESS static void* adjustScopeMarkerForAdressSanitizer(void* scopeMarker)
-{
- Address start = reinterpret_cast<Address>(getStackStart());
- Address end = reinterpret_cast<Address>(&start);
- RELEASE_ASSERT(end < start);
-
- if (end <= scopeMarker && scopeMarker < start)
- return scopeMarker;
-
- // 256 is as good an approximation as any else.
- const size_t bytesToCopy = sizeof(Address) * 256;
- if (static_cast<size_t>(start - end) < bytesToCopy)
- return start;
-
- return end + bytesToCopy;
-}
-#endif
-
-void ThreadState::enterSafePoint(StackState stackState, void* scopeMarker)
-{
-#ifdef ADDRESS_SANITIZER
- if (stackState == HeapPointersOnStack)
- scopeMarker = adjustScopeMarkerForAdressSanitizer(scopeMarker);
-#endif
- ASSERT(stackState == NoHeapPointersOnStack || scopeMarker);
- performPendingGC(stackState);
- checkThread();
- ASSERT(!m_atSafePoint);
- m_atSafePoint = true;
- m_stackState = stackState;
- m_safePointScopeMarker = scopeMarker;
- s_safePointBarrier->enterSafePoint(this);
-}
-
-void ThreadState::leaveSafePoint(SafePointAwareMutexLocker* locker)
-{
- checkThread();
- ASSERT(m_atSafePoint);
- s_safePointBarrier->leaveSafePoint(this, locker);
- m_atSafePoint = false;
- m_stackState = HeapPointersOnStack;
- clearSafePointScopeMarker();
- performPendingSweep();
-}
-
-void ThreadState::copyStackUntilSafePointScope()
-{
- if (!m_safePointScopeMarker || m_stackState == NoHeapPointersOnStack)
- return;
-
- Address* to = reinterpret_cast<Address*>(m_safePointScopeMarker);
- Address* from = reinterpret_cast<Address*>(m_endOfStack);
- RELEASE_ASSERT(from < to);
- RELEASE_ASSERT(to <= reinterpret_cast<Address*>(m_startOfStack));
- size_t slotCount = static_cast<size_t>(to - from);
- // Catch potential performance issues.
-#if defined(LEAK_SANITIZER) || defined(ADDRESS_SANITIZER)
- // ASan/LSan use more space on the stack and we therefore
- // increase the allowed stack copying for those builds.
- ASSERT(slotCount < 2048);
-#else
- ASSERT(slotCount < 1024);
-#endif
-
- ASSERT(!m_safePointStackCopy.size());
- m_safePointStackCopy.resize(slotCount);
- for (size_t i = 0; i < slotCount; ++i) {
- m_safePointStackCopy[i] = from[i];
- }
-}
-
-void ThreadState::registerSweepingTask()
-{
- MutexLocker locker(m_sweepMutex);
- ++m_numberOfSweeperTasks;
-}
-
-void ThreadState::unregisterSweepingTask()
-{
- MutexLocker locker(m_sweepMutex);
- ASSERT(m_numberOfSweeperTasks > 0);
- if (!--m_numberOfSweeperTasks)
- m_sweepThreadCondition.signal();
-}
-
-void ThreadState::waitUntilSweepersDone()
-{
- MutexLocker locker(m_sweepMutex);
- while (m_numberOfSweeperTasks > 0)
- m_sweepThreadCondition.wait(m_sweepMutex);
-}
-
-void ThreadState::performPendingSweep()
-{
-}
-
-void ThreadState::addInterruptor(Interruptor* interruptor)
-{
- SafePointScope scope(HeapPointersOnStack, SafePointScope::AllowNesting);
-
- {
- MutexLocker locker(threadAttachMutex());
- m_interruptors.append(interruptor);
- }
-}
-
-void ThreadState::removeInterruptor(Interruptor* interruptor)
-{
- SafePointScope scope(HeapPointersOnStack, SafePointScope::AllowNesting);
-
- {
- MutexLocker locker(threadAttachMutex());
- size_t index = m_interruptors.find(interruptor);
- RELEASE_ASSERT(index >= 0);
- m_interruptors.remove(index);
- }
-}
-
-void ThreadState::Interruptor::onInterrupted()
-{
- ThreadState* state = ThreadState::current();
- ASSERT(state);
- ASSERT(!state->isAtSafePoint());
- state->safePoint(HeapPointersOnStack);
-}
-
-ThreadState::AttachedThreadStateSet& ThreadState::attachedThreads()
-{
- DEFINE_STATIC_LOCAL(AttachedThreadStateSet, threads, ());
- return threads;
-}
-
-#if ENABLE(GC_PROFILE_MARKING)
-const GCInfo* ThreadState::findGCInfoFromAllThreads(Address address)
-{
- bool needLockForIteration = !isAnyThreadInGC();
- if (needLockForIteration)
- threadAttachMutex().lock();
-
- ThreadState::AttachedThreadStateSet& threads = attachedThreads();
- for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end = threads.end(); it != end; ++it) {
- if (const GCInfo* gcInfo = (*it)->findGCInfo(address)) {
- if (needLockForIteration)
- threadAttachMutex().unlock();
- return gcInfo;
- }
- }
- if (needLockForIteration)
- threadAttachMutex().unlock();
- return 0;
-}
-#endif
-
-}
« no previous file with comments | « sky/engine/platform/heap/ThreadState.h ('k') | sky/engine/platform/heap/Visitor.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698