109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)/* 209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * Copyright (C) 2013 Google Inc. All rights reserved. 309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * 409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without 509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * modification, are permitted provided that the following conditions are 609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * met: 709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * 809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * * Redistributions of source code must retain the above copyright 909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * notice, this list of conditions and the following disclaimer. 1009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * * Redistributions in binary form must reproduce the above 1109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer 1209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * in the documentation and/or other materials provided with the 1309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * distribution. 1409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * * Neither the name of Google Inc. nor the names of its 1509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * contributors may be used to endorse or promote products derived from 1609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * this software without specific prior written permission. 1709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * 1809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) */ 3009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 3109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "config.h" 32a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include "platform/heap/ThreadState.h" 3309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 34197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "platform/ScriptForbiddenScope.h" 35323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)#include "platform/TraceEvent.h" 36a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include "platform/heap/AddressSanitizer.h" 377242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "platform/heap/CallbackStack.h" 38a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include "platform/heap/Handle.h" 39a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include "platform/heap/Heap.h" 40f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)#include "public/platform/Platform.h" 419e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)#include "public/platform/WebThread.h" 4209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "wtf/ThreadingPrimitives.h" 43e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#if ENABLE(GC_PROFILE_HEAP) 44e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#include "platform/TracedValue.h" 45e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#endif 4609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 4709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#if OS(WIN) 4809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include <stddef.h> 4909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include <windows.h> 5009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include <winnt.h> 5109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#elif defined(__GLIBC__) 5209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)extern "C" void* __libc_stack_end; // NOLINT 5309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#endif 5409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 55d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)#if defined(MEMORY_SANITIZER) 56d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)#include <sanitizer/msan_interface.h> 57d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)#endif 58d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 59c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink { 6009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 6109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)static void* getStackStart() 6209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 6309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#if defined(__GLIBC__) || OS(ANDROID) 6409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) pthread_attr_t attr; 6509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (!pthread_getattr_np(pthread_self(), &attr)) { 6609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) void* base; 6709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) size_t size; 6809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) int error = pthread_attr_getstack(&attr, &base, &size); 6909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) RELEASE_ASSERT(!error); 7009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) pthread_attr_destroy(&attr); 7109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) return reinterpret_cast<Address>(base) + size; 7209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 7309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#if defined(__GLIBC__) 7409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // pthread_getattr_np can fail for the main thread. In this case 7509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // just like NaCl we rely on the __libc_stack_end to give us 7609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // the start of the stack. 7709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // See https://code.google.com/p/nativeclient/issues/detail?id=3431. 7809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) return __libc_stack_end; 7909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#else 8009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ASSERT_NOT_REACHED(); 8109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) return 0; 8209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#endif 8309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#elif OS(MACOSX) 8409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) return pthread_get_stackaddr_np(pthread_self()); 8509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#elif OS(WIN) && COMPILER(MSVC) 8609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // On Windows stack limits for the current thread are available in 8709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // the thread information block (TIB). Its fields can be accessed through 8809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // FS segment register on x86 and GS segment register on x86_64. 8909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#ifdef _WIN64 9009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) return reinterpret_cast<void*>(__readgsqword(offsetof(NT_TIB64, StackBase))); 9109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#else 9209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) return reinterpret_cast<void*>(__readfsdword(offsetof(NT_TIB, StackBase))); 9309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#endif 9409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#else 9509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#error Unsupported getStackStart on this platform. 9609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#endif 9709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 9809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 997242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// The maximum number of WrapperPersistentRegions to keep around in the 1007242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// m_pooledWrapperPersistentRegions pool. 1017242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccistatic const size_t MaxPooledWrapperPersistentRegionCount = 2; 10209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 10309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)WTF::ThreadSpecific<ThreadState*>* ThreadState::s_threadSpecific = 0; 10409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)uint8_t ThreadState::s_mainThreadStateStorage[sizeof(ThreadState)]; 10509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)SafePointBarrier* ThreadState::s_safePointBarrier = 0; 10609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)bool ThreadState::s_inGC = false; 10709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 10809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)static Mutex& threadAttachMutex() 10909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 11009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex); 11109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) return mutex; 11209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 11309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 114323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)static double lockingTimeout() 115323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles){ 1165d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) // Wait time for parking all threads is at most 100 MS. 117323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) return 0.100; 118323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)} 119323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) 120323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) 12109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)typedef void (*PushAllRegistersCallback)(SafePointBarrier*, ThreadState*, intptr_t*); 12209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)extern "C" void pushAllRegisters(SafePointBarrier*, ThreadState*, PushAllRegistersCallback); 12309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 12409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)class SafePointBarrier { 12509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)public: 12609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) SafePointBarrier() : m_canResume(1), m_unparkedThreadCount(0) { } 12709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ~SafePointBarrier() { } 12809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 12909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // Request other attached threads that are not at safe points to park themselves on safepoints. 130323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) bool parkOthers() 13109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) { 13209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ASSERT(ThreadState::current()->isAtSafePoint()); 13309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 13409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // Lock threadAttachMutex() to prevent threads from attaching. 13509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) threadAttachMutex().lock(); 13609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 13709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThreads(); 13809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 13909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) MutexLocker locker(m_mutex); 14009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) atomicAdd(&m_unparkedThreadCount, threads.size()); 14143e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) releaseStore(&m_canResume, 0); 14209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 14309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ThreadState* current = ThreadState::current(); 14409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end = threads.end(); it != end; ++it) { 14509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (*it == current) 14609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) continue; 14709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 14809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) const Vector<ThreadState::Interruptor*>& interruptors = (*it)->interruptors(); 14909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) for (size_t i = 0; i < interruptors.size(); i++) 15009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) interruptors[i]->requestInterrupt(); 15109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 15209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 153323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) while (acquireLoad(&m_unparkedThreadCount) > 0) { 154323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) double expirationTime = currentTime() + lockingTimeout(); 155323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) if (!m_parked.timedWait(m_mutex, expirationTime)) { 156323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) // One of the other threads did not return to a safepoint within the maximum 157323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) // time we allow for threads to be parked. Abandon the GC and resume the 158323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) // currently parked threads. 159323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) resumeOthers(true); 160323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) return false; 161323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) } 162323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) } 163323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) return true; 16409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 16509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 166323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) void resumeOthers(bool barrierLocked = false) 16709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) { 16809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThreads(); 16909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) atomicSubtract(&m_unparkedThreadCount, threads.size()); 17043e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) releaseStore(&m_canResume, 1); 171323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) 172323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) // FIXME: Resumed threads will all contend for m_mutex just to unlock it 173323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) // later which is a waste of resources. 174323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) if (UNLIKELY(barrierLocked)) { 175323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) m_resume.broadcast(); 176323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) } else { 17709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // FIXME: Resumed threads will all contend for 17809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // m_mutex just to unlock it later which is a waste of 17909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // resources. 18009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) MutexLocker locker(m_mutex); 18109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) m_resume.broadcast(); 18209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 18309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 18409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ThreadState* current = ThreadState::current(); 18509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end = threads.end(); it != end; ++it) { 18609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (*it == current) 18709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) continue; 18809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 18909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) const Vector<ThreadState::Interruptor*>& interruptors = (*it)->interruptors(); 19009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) for (size_t i = 0; i < interruptors.size(); i++) 19109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) interruptors[i]->clearInterrupt(); 19209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 19309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 19409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) threadAttachMutex().unlock(); 19509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ASSERT(ThreadState::current()->isAtSafePoint()); 19609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 19709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 1985d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) void checkAndPark(ThreadState* state, SafePointAwareMutexLocker* locker = 0) 199323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) { 200323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) ASSERT(!state->isSweepInProgress()); 201323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) if (!acquireLoad(&m_canResume)) { 2025d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) // If we are leaving the safepoint from a SafePointAwareMutexLocker 2035d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) // call out to release the lock before going to sleep. This enables the 2045d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) // lock to be acquired in the sweep phase, e.g. during weak processing 2055d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) // or finalization. The SafePointAwareLocker will reenter the safepoint 2065d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) // and reacquire the lock after leaving this safepoint. 2075d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) if (locker) 2085d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) locker->reset(); 209323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) pushAllRegisters(this, state, parkAfterPushRegisters); 210323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) } 211323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) } 212323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) 213323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) void enterSafePoint(ThreadState* state) 214323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) { 215323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) ASSERT(!state->isSweepInProgress()); 216323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) pushAllRegisters(this, state, enterSafePointAfterPushRegisters); 217323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) } 218323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) 2195d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) void leaveSafePoint(ThreadState* state, SafePointAwareMutexLocker* locker = 0) 220323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) { 221323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) if (atomicIncrement(&m_unparkedThreadCount) > 0) 2225d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) checkAndPark(state, locker); 223323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) } 224323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) 225323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)private: 22609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) void doPark(ThreadState* state, intptr_t* stackEnd) 22709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) { 22809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) state->recordStackEnd(stackEnd); 22909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) MutexLocker locker(m_mutex); 23009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (!atomicDecrement(&m_unparkedThreadCount)) 23109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) m_parked.signal(); 23243e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) while (!acquireLoad(&m_canResume)) 23309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) m_resume.wait(m_mutex); 23409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) atomicIncrement(&m_unparkedThreadCount); 23509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 23609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 237323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) static void parkAfterPushRegisters(SafePointBarrier* barrier, ThreadState* state, intptr_t* stackEnd) 23809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) { 239323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) barrier->doPark(state, stackEnd); 24009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 24109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 24209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) void doEnterSafePoint(ThreadState* state, intptr_t* stackEnd) 24309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) { 24409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) state->recordStackEnd(stackEnd); 245aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch state->copyStackUntilSafePointScope(); 24609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // m_unparkedThreadCount tracks amount of unparked threads. It is 24709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // positive if and only if we have requested other threads to park 24809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // at safe-points in preparation for GC. The last thread to park 24909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // itself will make the counter hit zero and should notify GC thread 25009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // that it is safe to proceed. 25109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // If no other thread is waiting for other threads to park then 25209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // this counter can be negative: if N threads are at safe-points 25309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // the counter will be -N. 25409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (!atomicDecrement(&m_unparkedThreadCount)) { 25509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) MutexLocker locker(m_mutex); 25609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) m_parked.signal(); // Safe point reached. 25709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 25809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 25909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 26009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) static void enterSafePointAfterPushRegisters(SafePointBarrier* barrier, ThreadState* state, intptr_t* stackEnd) 26109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) { 26209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) barrier->doEnterSafePoint(state, stackEnd); 26309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 26409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 26509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) volatile int m_canResume; 26609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) volatile int m_unparkedThreadCount; 26709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) Mutex m_mutex; 26809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ThreadCondition m_parked; 26909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ThreadCondition m_resume; 27009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}; 27109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 272197021e6b966cfb06891637935ef33fff06433d1Ben MurdochBaseHeapPage::BaseHeapPage(PageMemory* storage, const GCInfo* gcInfo, ThreadState* state) 273197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch : m_storage(storage) 274197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch , m_gcInfo(gcInfo) 275197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch , m_threadState(state) 276197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch , m_terminating(false) 277197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch , m_tracedAfterOrphaned(false) 278197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch{ 279197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch ASSERT(isPageHeaderAddress(reinterpret_cast<Address>(this))); 280197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch} 281197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 2829e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)// Statically unfold the heap initialization loop so the compiler statically 2839e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)// knows the heap index when using HeapIndexTrait. 2849e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)template<int num> struct InitializeHeaps { 2859e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) static const int index = num - 1; 2869e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) static void init(BaseHeap** heaps, ThreadState* state) 2879e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) { 2889e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) InitializeHeaps<index>::init(heaps, state); 2899e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) heaps[index] = new typename HeapIndexTrait<index>::HeapType(state, index); 2909e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) } 2919e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)}; 2929e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)template<> struct InitializeHeaps<0> { 2939e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) static void init(BaseHeap** heaps, ThreadState* state) { } 2949e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)}; 2959e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) 29609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)ThreadState::ThreadState() 29709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) : m_thread(currentThread()) 2987242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci , m_liveWrapperPersistents(new WrapperPersistentRegion()) 2997242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci , m_pooledWrapperPersistents(0) 3007242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci , m_pooledWrapperPersistentRegionCount(0) 301d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) , m_persistents(adoptPtr(new PersistentAnchor())) 30209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) , m_startOfStack(reinterpret_cast<intptr_t*>(getStackStart())) 30309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) , m_endOfStack(reinterpret_cast<intptr_t*>(getStackStart())) 30409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) , m_safePointScopeMarker(0) 30509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) , m_atSafePoint(false) 30609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) , m_interruptors() 30709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) , m_gcRequested(false) 308aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch , m_forcePreciseGCForTesting(false) 30909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) , m_sweepRequested(0) 31009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) , m_sweepInProgress(false) 31109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) , m_noAllocationCount(0) 31209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) , m_inGC(false) 313d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) , m_heapContainsCache(adoptPtr(new HeapContainsCache())) 314197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch , m_isTerminating(false) 315e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) , m_lowCollectionRate(false) 3169e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) , m_numberOfSweeperTasks(0) 317f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#if defined(ADDRESS_SANITIZER) 318a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch , m_asanFakeStack(__asan_get_current_fake_stack()) 319a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#endif 32009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 32109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ASSERT(!**s_threadSpecific); 32209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) **s_threadSpecific = this; 32309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 3249e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) InitializeHeaps<NumberOfHeaps>::init(m_heaps, this); 325d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 3267242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci m_weakCallbackStack = new CallbackStack(); 3279e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) 3289e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) if (blink::Platform::current()) 3299e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) m_sweeperThread = adoptPtr(blink::Platform::current()->createThread("Blink GC Sweeper")); 33009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 33109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 33209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)ThreadState::~ThreadState() 33309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 33409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) checkThread(); 3357242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci delete m_weakCallbackStack; 3367242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci m_weakCallbackStack = 0; 3379e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) for (int i = 0; i < NumberOfHeaps; i++) 33809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) delete m_heaps[i]; 33909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) deleteAllValues(m_interruptors); 3407242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci while (m_liveWrapperPersistents) { 3417242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci WrapperPersistentRegion* region = WrapperPersistentRegion::removeHead(&m_liveWrapperPersistents); 3427242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci delete region; 3437242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci } 3447242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci while (m_pooledWrapperPersistents) { 3457242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci WrapperPersistentRegion* region = WrapperPersistentRegion::removeHead(&m_pooledWrapperPersistents); 3467242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci delete region; 3477242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci } 34809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) **s_threadSpecific = 0; 34909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 35009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 35109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void ThreadState::init() 35209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 35309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) s_threadSpecific = new WTF::ThreadSpecific<ThreadState*>(); 35409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) s_safePointBarrier = new SafePointBarrier; 35509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 35609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 35709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void ThreadState::shutdown() 35809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 3596f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch delete s_safePointBarrier; 3606f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch s_safePointBarrier = 0; 36110f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch 36210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch // Thread-local storage shouldn't be disposed, so we don't call ~ThreadSpecific(). 3636f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch} 3646f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch 3656f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdochvoid ThreadState::attachMainThread() 3666f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch{ 36710f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch RELEASE_ASSERT(!Heap::s_shutdownCalled); 3686f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch MutexLocker locker(threadAttachMutex()); 3696f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch ThreadState* state = new(s_mainThreadStateStorage) ThreadState(); 3706f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch attachedThreads().add(state); 3716f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch} 3726f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch 3736f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdochvoid ThreadState::detachMainThread() 3746f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch{ 37510f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch // Enter a safe point before trying to acquire threadAttachMutex 37610f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch // to avoid dead lock if another thread is preparing for GC, has acquired 37710f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch // threadAttachMutex and waiting for other threads to pause or reach a 37810f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch // safepoint. 3796f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch ThreadState* state = mainThreadState(); 38010f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch 38110f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch { 382197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch SafePointAwareMutexLocker locker(threadAttachMutex(), NoHeapPointersOnStack); 383197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 384197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // First add the main thread's heap pages to the orphaned pool. 385197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch state->cleanupPages(); 386197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 387197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // Second detach thread. 38810f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch ASSERT(attachedThreads().contains(state)); 38910f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch attachedThreads().remove(state); 39010f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch state->~ThreadState(); 39110f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch } 39210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch shutdownHeapIfNecessary(); 39310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch} 39410f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch 39510f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdochvoid ThreadState::shutdownHeapIfNecessary() 39610f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch{ 39710f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch // We don't need to enter a safe point before acquiring threadAttachMutex 39810f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch // because this thread is already detached. 39910f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch 40010f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch MutexLocker locker(threadAttachMutex()); 40110f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch // We start shutting down the heap if there is no running thread 40210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch // and Heap::shutdown() is already called. 40310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch if (!attachedThreads().size() && Heap::s_shutdownCalled) 40410f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch Heap::doShutdown(); 40509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 40609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 40709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void ThreadState::attach() 40809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 40910f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch RELEASE_ASSERT(!Heap::s_shutdownCalled); 41009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) MutexLocker locker(threadAttachMutex()); 41109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ThreadState* state = new ThreadState(); 41209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) attachedThreads().add(state); 41309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 41409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 415197021e6b966cfb06891637935ef33fff06433d1Ben Murdochvoid ThreadState::cleanupPages() 41609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 4179e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) for (int i = 0; i < NumberOfHeaps; ++i) 418197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch m_heaps[i]->cleanupPages(); 419197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch} 42009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 421197021e6b966cfb06891637935ef33fff06433d1Ben Murdochvoid ThreadState::cleanup() 422197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch{ 42309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) for (size_t i = 0; i < m_cleanupTasks.size(); i++) 42409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) m_cleanupTasks[i]->preCleanup(); 42509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 426197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch { 427197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // Grab the threadAttachMutex to ensure only one thread can shutdown at 428197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // a time and that no other thread can do a global GC. It also allows 429197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // safe iteration of the attachedThreads set which happens as part of 430197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // thread local GC asserts. We enter a safepoint while waiting for the 431197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // lock to avoid a dead-lock where another thread has already requested 432197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // GC. 433197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch SafePointAwareMutexLocker locker(threadAttachMutex(), NoHeapPointersOnStack); 434197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 435197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // From here on ignore all conservatively discovered 436197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // pointers into the heap owned by this thread. 437197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch m_isTerminating = true; 438197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 439197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // Set the terminate flag on all heap pages of this thread. This is used to 440197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // ensure we don't trace pages on other threads that are not part of the 441197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // thread local GC. 442197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch setupHeapsForTermination(); 443197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 444197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // Do thread local GC's as long as the count of thread local Persistents 445197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // changes and is above zero. 446197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch PersistentAnchor* anchor = static_cast<PersistentAnchor*>(m_persistents.get()); 447197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch int oldCount = -1; 448197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch int currentCount = anchor->numberOfPersistents(); 449197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch ASSERT(currentCount >= 0); 450197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch while (currentCount != oldCount) { 451197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch Heap::collectGarbageForTerminatingThread(this); 452197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch oldCount = currentCount; 453197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch currentCount = anchor->numberOfPersistents(); 454197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch } 455197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // We should not have any persistents left when getting to this point, 456197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // if we have it is probably a bug so adding a debug ASSERT to catch this. 457197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch ASSERT(!currentCount); 45809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 459197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // Add pages to the orphaned page pool to ensure any global GCs from this point 460197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // on will not trace objects on this thread's heaps. 461197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch cleanupPages(); 462197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 463197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch ASSERT(attachedThreads().contains(this)); 464197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch attachedThreads().remove(this); 465197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch } 46609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 46709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) for (size_t i = 0; i < m_cleanupTasks.size(); i++) 46809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) m_cleanupTasks[i]->postCleanup(); 46909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) m_cleanupTasks.clear(); 47009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 47109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 472197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 47309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void ThreadState::detach() 47409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 47509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ThreadState* state = current(); 476d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) state->cleanup(); 477197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch delete state; 47810f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch shutdownHeapIfNecessary(); 47909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 48009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 481c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void ThreadState::visitPersistentRoots(Visitor* visitor) 48209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 4837242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci TRACE_EVENT0("blink_gc", "ThreadState::visitPersistentRoots"); 48409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) { 48509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // All threads are at safepoints so this is not strictly necessary. 48609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // However we acquire the mutex to make mutation and traversal of this 48709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // list symmetrical. 48809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) MutexLocker locker(globalRootsMutex()); 48909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) globalRoots()->trace(visitor); 49009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 49109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 49209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) AttachedThreadStateSet& threads = attachedThreads(); 49309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) for (AttachedThreadStateSet::iterator it = threads.begin(), end = threads.end(); it != end; ++it) 494c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) (*it)->visitPersistents(visitor); 49509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 49609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 497c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void ThreadState::visitStackRoots(Visitor* visitor) 498197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch{ 4997242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci TRACE_EVENT0("blink_gc", "ThreadState::visitStackRoots"); 500c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) AttachedThreadStateSet& threads = attachedThreads(); 501c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) for (AttachedThreadStateSet::iterator it = threads.begin(), end = threads.end(); it != end; ++it) 502c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) (*it)->visitStack(visitor); 503197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch} 504197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 50509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)NO_SANITIZE_ADDRESS 506a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochvoid ThreadState::visitAsanFakeStackForPointer(Visitor* visitor, Address ptr) 507a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch{ 508f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#if defined(ADDRESS_SANITIZER) 509a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch Address* start = reinterpret_cast<Address*>(m_startOfStack); 510a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch Address* end = reinterpret_cast<Address*>(m_endOfStack); 511a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch Address* fakeFrameStart = 0; 512a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch Address* fakeFrameEnd = 0; 513a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch Address* maybeFakeFrame = reinterpret_cast<Address*>(ptr); 514a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch Address* realFrameForFakeFrame = 515a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch reinterpret_cast<Address*>( 516a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch __asan_addr_is_in_fake_stack( 517a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch m_asanFakeStack, maybeFakeFrame, 518a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch reinterpret_cast<void**>(&fakeFrameStart), 519a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch reinterpret_cast<void**>(&fakeFrameEnd))); 520a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (realFrameForFakeFrame) { 521a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // This is a fake frame from the asan fake stack. 522a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (realFrameForFakeFrame > end && start > realFrameForFakeFrame) { 523a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // The real stack address for the asan fake frame is 524a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // within the stack range that we need to scan so we need 525a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // to visit the values in the fake frame. 526a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch for (Address* p = fakeFrameStart; p < fakeFrameEnd; p++) 527a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch Heap::checkAndMarkPointer(visitor, *p); 528a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 529a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 530a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#endif 531a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch} 532a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 533a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben MurdochNO_SANITIZE_ADDRESS 53409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void ThreadState::visitStack(Visitor* visitor) 53509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 536c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (m_stackState == NoHeapPointersOnStack) 537c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) return; 538c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 53909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) Address* start = reinterpret_cast<Address*>(m_startOfStack); 54009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // If there is a safepoint scope marker we should stop the stack 54109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // scanning there to not touch active parts of the stack. Anything 54209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // interesting beyond that point is in the safepoint stack copy. 54309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // If there is no scope marker the thread is blocked and we should 54409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // scan all the way to the recorded end stack pointer. 54509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) Address* end = reinterpret_cast<Address*>(m_endOfStack); 54609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) Address* safePointScopeMarker = reinterpret_cast<Address*>(m_safePointScopeMarker); 54709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) Address* current = safePointScopeMarker ? safePointScopeMarker : end; 54809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 54909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // Ensure that current is aligned by address size otherwise the loop below 55009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // will read past start address. 55109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) current = reinterpret_cast<Address*>(reinterpret_cast<intptr_t>(current) & ~(sizeof(Address) - 1)); 55209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 553a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch for (; current < start; ++current) { 554d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) Address ptr = *current; 555d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)#if defined(MEMORY_SANITIZER) 556f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) // |ptr| may be uninitialized by design. Mark it as initialized to keep 557d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) // MSan from complaining. 558f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) // Note: it may be tempting to get rid of |ptr| and simply use |current| 559f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) // here, but that would be incorrect. We intentionally use a local 560f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) // variable because we don't want to unpoison the original stack. 561d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) __msan_unpoison(&ptr, sizeof(ptr)); 562d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)#endif 563d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) Heap::checkAndMarkPointer(visitor, ptr); 564d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) visitAsanFakeStackForPointer(visitor, ptr); 565a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 56609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 567a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch for (Vector<Address>::iterator it = m_safePointStackCopy.begin(); it != m_safePointStackCopy.end(); ++it) { 568f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) Address ptr = *it; 569f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)#if defined(MEMORY_SANITIZER) 570f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) // See the comment above. 571f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) __msan_unpoison(&ptr, sizeof(ptr)); 572f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)#endif 573f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) Heap::checkAndMarkPointer(visitor, ptr); 574f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) visitAsanFakeStackForPointer(visitor, ptr); 575a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 57609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 57709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 57809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void ThreadState::visitPersistents(Visitor* visitor) 57909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 58009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) m_persistents->trace(visitor); 5817242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci WrapperPersistentRegion::trace(m_liveWrapperPersistents, visitor); 58209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 58309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 58409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)bool ThreadState::checkAndMarkPointer(Visitor* visitor, Address address) 58509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 586197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // If thread is terminating ignore conservative pointers. 587197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch if (m_isTerminating) 58809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) return false; 58909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 590f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles) // This checks for normal pages and for large objects which span the extent 591f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles) // of several normal pages. 59209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) BaseHeapPage* page = heapPageFromAddress(address); 593f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles) if (page) { 594f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles) page->checkAndMarkPointer(visitor, address); 595f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles) // Whether or not the pointer was within an object it was certainly 596f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles) // within a page that is part of the heap, so we don't want to ask the 597f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles) // other other heaps or put this address in the 598f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles) // HeapDoesNotContainCache. 599f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles) return true; 60009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 601f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles) 60209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) return false; 60309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 60409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 605e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#if ENABLE(GC_PROFILE_MARKING) 606f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liuconst GCInfo* ThreadState::findGCInfo(Address address) 607f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu{ 608f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu BaseHeapPage* page = heapPageFromAddress(address); 609f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu if (page) { 610f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu return page->findGCInfo(address); 611f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu } 612f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu return 0; 613f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu} 614f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#endif 615f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu 616e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#if ENABLE(GC_PROFILE_HEAP) 617e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)size_t ThreadState::SnapshotInfo::getClassTag(const GCInfo* gcinfo) 618e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles){ 619e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) HashMap<const GCInfo*, size_t>::AddResult result = classTags.add(gcinfo, classTags.size()); 620e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) if (result.isNewEntry) { 621e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) liveCount.append(0); 622e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) deadCount.append(0); 6239e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) liveSize.append(0); 6249e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) deadSize.append(0); 625e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) generations.append(Vector<int, 8>()); 626e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) generations.last().fill(0, 8); 627e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) } 628e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) return result.storedValue->value; 629e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)} 630e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) 631e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)void ThreadState::snapshot() 632e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles){ 633e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) SnapshotInfo info(this); 634e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) RefPtr<TracedValue> json = TracedValue::create(); 635e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) 6369e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)#define SNAPSHOT_HEAP(HeapType) \ 6379e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) { \ 6389e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) json->beginDictionary(); \ 6399e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) json->setString("name", #HeapType); \ 6409e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) m_heaps[HeapType##Heap]->snapshot(json.get(), &info); \ 6419e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) json->endDictionary(); \ 6429e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) json->beginDictionary(); \ 6437242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci json->setString("name", #HeapType"NonFinalized"); \ 6449e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) m_heaps[HeapType##HeapNonFinalized]->snapshot(json.get(), &info); \ 6459e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) json->endDictionary(); \ 646e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) } 647e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) json->beginArray("heaps"); 648e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) SNAPSHOT_HEAP(General); 6497242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci SNAPSHOT_HEAP(CollectionBacking); 650e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) FOR_EACH_TYPED_HEAP(SNAPSHOT_HEAP); 651e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) json->endArray(); 652e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#undef SNAPSHOT_HEAP 653e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) 654e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) json->setInteger("allocatedSpace", m_stats.totalAllocatedSpace()); 655e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) json->setInteger("objectSpace", m_stats.totalObjectSpace()); 6567242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci json->setInteger("pageCount", info.pageCount); 6579e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) json->setInteger("freeSize", info.freeSize); 658e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) 659e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) Vector<String> classNameVector(info.classTags.size()); 660e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) for (HashMap<const GCInfo*, size_t>::iterator it = info.classTags.begin(); it != info.classTags.end(); ++it) 661e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) classNameVector[it->value] = it->key->m_className; 662e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) 6639e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) size_t liveSize = 0; 6649e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) size_t deadSize = 0; 665e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) json->beginArray("classes"); 666e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) for (size_t i = 0; i < classNameVector.size(); ++i) { 667e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) json->beginDictionary(); 668e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) json->setString("name", classNameVector[i]); 669e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) json->setInteger("liveCount", info.liveCount[i]); 670e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) json->setInteger("deadCount", info.deadCount[i]); 6719e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) json->setInteger("liveSize", info.liveSize[i]); 6729e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) json->setInteger("deadSize", info.deadSize[i]); 6739e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) liveSize += info.liveSize[i]; 6749e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) deadSize += info.deadSize[i]; 6759e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) 676e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) json->beginArray("generations"); 677e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) for (size_t j = 0; j < heapObjectGenerations; ++j) 678e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) json->pushInteger(info.generations[i][j]); 679e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) json->endArray(); 680e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) json->endDictionary(); 681e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) } 682e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) json->endArray(); 6839e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) json->setInteger("liveSize", liveSize); 6849e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) json->setInteger("deadSize", deadSize); 685e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) 6869e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID("blink_gc", "ThreadState", this, json.release()); 687e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)} 688e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#endif 689e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) 690d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)void ThreadState::pushWeakObjectPointerCallback(void* object, WeakPointerCallback callback) 691d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){ 6927242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci CallbackStack::Item* slot = m_weakCallbackStack->allocateEntry(); 693d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) *slot = CallbackStack::Item(object, callback); 694d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)} 695d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 696d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)bool ThreadState::popAndInvokeWeakPointerCallback(Visitor* visitor) 697d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){ 6987242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // For weak processing we should never reach orphaned pages since orphaned 6997242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // pages are not traced and thus objects on those pages are never be 7007242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // registered as objects on orphaned pages. We cannot assert this here since 7017242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // we might have an off-heap collection. We assert it in 7027242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // Heap::pushWeakObjectPointerCallback. 7037242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci if (CallbackStack::Item* item = m_weakCallbackStack->pop()) { 7047242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci item->call(visitor); 7057242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci return true; 7067242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci } 7077242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci return false; 7087242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci} 7097242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 7107242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano TucciWrapperPersistentRegion* ThreadState::takeWrapperPersistentRegion() 7117242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci{ 7127242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci WrapperPersistentRegion* region; 7137242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci if (m_pooledWrapperPersistentRegionCount) { 7147242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci region = WrapperPersistentRegion::removeHead(&m_pooledWrapperPersistents); 7157242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci m_pooledWrapperPersistentRegionCount--; 7167242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci } else { 7177242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci region = new WrapperPersistentRegion(); 7187242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci } 7197242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci ASSERT(region); 7207242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci WrapperPersistentRegion::insertHead(&m_liveWrapperPersistents, region); 7217242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci return region; 7227242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci} 7237242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 7247242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccivoid ThreadState::freeWrapperPersistentRegion(WrapperPersistentRegion* region) 7257242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci{ 7267242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci if (!region->removeIfNotLast(&m_liveWrapperPersistents)) 7277242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci return; 7287242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 7297242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // Region was removed, ie. it was not the last region in the list. 7307242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci if (m_pooledWrapperPersistentRegionCount < MaxPooledWrapperPersistentRegionCount) { 7317242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci WrapperPersistentRegion::insertHead(&m_pooledWrapperPersistents, region); 7327242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci m_pooledWrapperPersistentRegionCount++; 7337242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci } else { 7347242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci delete region; 7357242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci } 736d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)} 737d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 73809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)PersistentNode* ThreadState::globalRoots() 73909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 74009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) AtomicallyInitializedStatic(PersistentNode*, anchor = new PersistentAnchor); 74109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) return anchor; 74209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 74309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 74409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)Mutex& ThreadState::globalRootsMutex() 74509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 74609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex); 74709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) return mutex; 74809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 74909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 75009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Trigger garbage collection on a 50% increase in size, but not for 751d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)// less than 512kbytes. 752e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)bool ThreadState::increasedEnoughToGC(size_t newSize, size_t oldSize) 75309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 754d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) if (newSize < 1 << 19) 75509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) return false; 756e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) size_t limit = oldSize + (oldSize >> 1); 757e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) return newSize > limit; 75809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 75909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 76009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// FIXME: The heuristics are local for a thread at this 76109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// point. Consider using heuristics that take memory for all threads 76209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// into account. 76309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)bool ThreadState::shouldGC() 76409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 765d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) // Do not GC during sweeping. We allow allocation during 766d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) // finalization, but those allocations are not allowed 767d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) // to lead to nested garbage collections. 768d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) return !m_sweepInProgress && increasedEnoughToGC(m_stats.totalObjectSpace(), m_statsAfterLastGC.totalObjectSpace()); 76909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 77009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 77109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Trigger conservative garbage collection on a 100% increase in size, 772e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)// but not for less than 4Mbytes. If the system currently has a low 773e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)// collection rate, then require a 300% increase in size. 774e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)bool ThreadState::increasedEnoughToForceConservativeGC(size_t newSize, size_t oldSize) 77509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 776d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) if (newSize < 1 << 22) 77709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) return false; 778e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) size_t limit = (m_lowCollectionRate ? 4 : 2) * oldSize; 779e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) return newSize > limit; 78009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 78109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 78209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// FIXME: The heuristics are local for a thread at this 78309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// point. Consider using heuristics that take memory for all threads 78409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// into account. 78509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)bool ThreadState::shouldForceConservativeGC() 78609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 787d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) // Do not GC during sweeping. We allow allocation during 788d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) // finalization, but those allocations are not allowed 789d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) // to lead to nested garbage collections. 790d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) return !m_sweepInProgress && increasedEnoughToForceConservativeGC(m_stats.totalObjectSpace(), m_statsAfterLastGC.totalObjectSpace()); 79109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 79209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 79309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)bool ThreadState::sweepRequested() 79409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 79509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ASSERT(isAnyThreadInGC() || checkThread()); 79609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) return m_sweepRequested; 79709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 79809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 79909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void ThreadState::setSweepRequested() 80009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 80109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // Sweep requested is set from the thread that initiates garbage 80209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // collection which could be different from the thread for this 80309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // thread state. Therefore the setting of m_sweepRequested needs a 80409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // barrier. 80509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) atomicTestAndSetToOne(&m_sweepRequested); 80609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 80709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 80809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void ThreadState::clearSweepRequested() 80909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 81009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) checkThread(); 81109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) m_sweepRequested = 0; 81209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 81309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 81409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)bool ThreadState::gcRequested() 81509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 81609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) checkThread(); 81709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) return m_gcRequested; 81809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 81909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 82009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void ThreadState::setGCRequested() 82109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 82209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) checkThread(); 82309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) m_gcRequested = true; 82409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 82509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 82609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void ThreadState::clearGCRequested() 82709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 82809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) checkThread(); 82909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) m_gcRequested = false; 83009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 83109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 832aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdochvoid ThreadState::performPendingGC(StackState stackState) 833aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch{ 834a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (stackState == NoHeapPointersOnStack) { 835a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (forcePreciseGCForTesting()) { 836a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch setForcePreciseGCForTesting(false); 837a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch Heap::collectAllGarbage(); 838a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } else if (gcRequested()) { 839a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch Heap::collectGarbage(NoHeapPointersOnStack); 840a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 841aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch } 842aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch} 843aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch 844a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochvoid ThreadState::setForcePreciseGCForTesting(bool value) 845aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch{ 846aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch checkThread(); 847aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch m_forcePreciseGCForTesting = value; 848aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch} 849aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch 850aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdochbool ThreadState::forcePreciseGCForTesting() 851aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch{ 852aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch checkThread(); 853aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch return m_forcePreciseGCForTesting; 854aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch} 855aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch 8569e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)void ThreadState::makeConsistentForSweeping() 8579e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles){ 8589e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) for (int i = 0; i < NumberOfHeaps; i++) 8599e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) m_heaps[i]->makeConsistentForSweeping(); 8609e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)} 8619e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) 8629e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)#if ENABLE(ASSERT) 8639e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)bool ThreadState::isConsistentForSweeping() 86409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 86509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) for (int i = 0; i < NumberOfHeaps; i++) { 8669e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) if (!m_heaps[i]->isConsistentForSweeping()) 86709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) return false; 86809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 86909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) return true; 87009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 8719e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)#endif 87209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 87309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void ThreadState::prepareForGC() 87409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 87509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) for (int i = 0; i < NumberOfHeaps; i++) { 87609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) BaseHeap* heap = m_heaps[i]; 8779e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) heap->makeConsistentForSweeping(); 878197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // If a new GC is requested before this thread got around to sweep, ie. due to the 879197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // thread doing a long running operation, we clear the mark bits and mark any of 880197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // the dead objects as dead. The latter is used to ensure the next GC marking does 881197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // not trace already dead objects. If we trace a dead object we could end up tracing 882197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // into garbage or the middle of another object via the newly conservatively found 883197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // object. 88409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (sweepRequested()) 885197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch heap->clearLiveAndMarkDead(); 88609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 88709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) setSweepRequested(); 88809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 88909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 890197021e6b966cfb06891637935ef33fff06433d1Ben Murdochvoid ThreadState::setupHeapsForTermination() 891197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch{ 892197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch for (int i = 0; i < NumberOfHeaps; i++) 893197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch m_heaps[i]->prepareHeapForTermination(); 894197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch} 895197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 89609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)BaseHeapPage* ThreadState::heapPageFromAddress(Address address) 89709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 898f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles) BaseHeapPage* cachedPage = heapContainsCache()->lookup(address); 899197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#if !ENABLE(ASSERT) 900f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles) if (cachedPage) 901f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles) return cachedPage; 90209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#endif 90309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 90409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) for (int i = 0; i < NumberOfHeaps; i++) { 905f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles) BaseHeapPage* page = m_heaps[i]->heapPageFromAddress(address); 906f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles) if (page) { 907f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles) // Asserts that make sure heapPageFromAddress takes addresses from 908f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles) // the whole aligned blinkPageSize memory area. This is necessary 909f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles) // for the negative cache to work. 910f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles) ASSERT(page->isLargeObject() || page == m_heaps[i]->heapPageFromAddress(roundToBlinkPageStart(address))); 911f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles) if (roundToBlinkPageStart(address) != roundToBlinkPageEnd(address)) 912f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles) ASSERT(page->isLargeObject() || page == m_heaps[i]->heapPageFromAddress(roundToBlinkPageEnd(address) - 1)); 913f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles) ASSERT(!cachedPage || page == cachedPage); 914f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles) if (!cachedPage) 915f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles) heapContainsCache()->addEntry(address, page); 916d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) return page; 917f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles) } 91809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 919f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles) ASSERT(!cachedPage); 920d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) return 0; 92109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 92209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 92309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void ThreadState::getStats(HeapStats& stats) 92409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 92509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) stats = m_stats; 926197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#if ENABLE(ASSERT) 9279e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) if (isConsistentForSweeping()) { 92809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) HeapStats scannedStats; 92909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) for (int i = 0; i < NumberOfHeaps; i++) 93009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) m_heaps[i]->getScannedStats(scannedStats); 93109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ASSERT(scannedStats == stats); 93209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 93309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#endif 93409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 93509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 936323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)bool ThreadState::stopThreads() 93709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 938323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) return s_safePointBarrier->parkOthers(); 93909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 94009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 94109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void ThreadState::resumeThreads() 94209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 94309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) s_safePointBarrier->resumeOthers(); 94409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 94509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 94609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void ThreadState::safePoint(StackState stackState) 94709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 94809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) checkThread(); 949aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch performPendingGC(stackState); 9505d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) ASSERT(!m_atSafePoint); 95109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) m_stackState = stackState; 9525d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) m_atSafePoint = true; 95309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) s_safePointBarrier->checkAndPark(this); 9545d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) m_atSafePoint = false; 95509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) m_stackState = HeapPointersOnStack; 956197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch performPendingSweep(); 95709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 95809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 95909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#ifdef ADDRESS_SANITIZER 96009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// When we are running under AddressSanitizer with detect_stack_use_after_return=1 96109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// then stack marker obtained from SafePointScope will point into a fake stack. 96209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Detect this case by checking if it falls in between current stack frame 96309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// and stack start and use an arbitrary high enough value for it. 96409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Don't adjust stack marker in any other case to match behavior of code running 96509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// without AddressSanitizer. 96609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)NO_SANITIZE_ADDRESS static void* adjustScopeMarkerForAdressSanitizer(void* scopeMarker) 96709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 96809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) Address start = reinterpret_cast<Address>(getStackStart()); 96909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) Address end = reinterpret_cast<Address>(&start); 97009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) RELEASE_ASSERT(end < start); 97109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 97209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (end <= scopeMarker && scopeMarker < start) 97309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) return scopeMarker; 97409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 97509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // 256 is as good an approximation as any else. 97609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) const size_t bytesToCopy = sizeof(Address) * 256; 977323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) if (static_cast<size_t>(start - end) < bytesToCopy) 97809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) return start; 97909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 98009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) return end + bytesToCopy; 98109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 98209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#endif 98309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 98409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void ThreadState::enterSafePoint(StackState stackState, void* scopeMarker) 98509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 98609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#ifdef ADDRESS_SANITIZER 98709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (stackState == HeapPointersOnStack) 98809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) scopeMarker = adjustScopeMarkerForAdressSanitizer(scopeMarker); 98909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#endif 99009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ASSERT(stackState == NoHeapPointersOnStack || scopeMarker); 991aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch performPendingGC(stackState); 99209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) checkThread(); 99309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ASSERT(!m_atSafePoint); 99409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) m_atSafePoint = true; 99509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) m_stackState = stackState; 99609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) m_safePointScopeMarker = scopeMarker; 99709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) s_safePointBarrier->enterSafePoint(this); 99809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 99909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 10005d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)void ThreadState::leaveSafePoint(SafePointAwareMutexLocker* locker) 100109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 100209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) checkThread(); 100309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ASSERT(m_atSafePoint); 10045d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) s_safePointBarrier->leaveSafePoint(this, locker); 100509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) m_atSafePoint = false; 100609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) m_stackState = HeapPointersOnStack; 100709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) clearSafePointScopeMarker(); 1008d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) performPendingSweep(); 100909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 101009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 101109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void ThreadState::copyStackUntilSafePointScope() 101209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 101309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (!m_safePointScopeMarker || m_stackState == NoHeapPointersOnStack) 101409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) return; 101509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 101609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) Address* to = reinterpret_cast<Address*>(m_safePointScopeMarker); 101709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) Address* from = reinterpret_cast<Address*>(m_endOfStack); 101809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) RELEASE_ASSERT(from < to); 1019f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu RELEASE_ASSERT(to <= reinterpret_cast<Address*>(m_startOfStack)); 102009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) size_t slotCount = static_cast<size_t>(to - from); 10219e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) // Catch potential performance issues. 10229e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)#if defined(LEAK_SANITIZER) || defined(ADDRESS_SANITIZER) 10239e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) // ASan/LSan use more space on the stack and we therefore 10249e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) // increase the allowed stack copying for those builds. 10259e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) ASSERT(slotCount < 2048); 10269e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)#else 10279e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) ASSERT(slotCount < 1024); 10289e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)#endif 102909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 103009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ASSERT(!m_safePointStackCopy.size()); 103109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) m_safePointStackCopy.resize(slotCount); 103209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) for (size_t i = 0; i < slotCount; ++i) { 103309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) m_safePointStackCopy[i] = from[i]; 103409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 103509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 103609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 10379e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)void ThreadState::registerSweepingTask() 10389e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles){ 10399e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) MutexLocker locker(m_sweepMutex); 10409e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) ++m_numberOfSweeperTasks; 10419e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)} 10429e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) 10439e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)void ThreadState::unregisterSweepingTask() 10449e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles){ 10459e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) MutexLocker locker(m_sweepMutex); 10469e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) ASSERT(m_numberOfSweeperTasks > 0); 10479e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) if (!--m_numberOfSweeperTasks) 10489e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) m_sweepThreadCondition.signal(); 10499e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)} 10509e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) 10519e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)void ThreadState::waitUntilSweepersDone() 10529e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles){ 10539e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) MutexLocker locker(m_sweepMutex); 10549e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) while (m_numberOfSweeperTasks > 0) 10559e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) m_sweepThreadCondition.wait(m_sweepMutex); 10569e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)} 10579e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) 10589e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) 10599e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)class SweepNonFinalizedHeapTask FINAL : public WebThread::Task { 10609e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)public: 10619e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) SweepNonFinalizedHeapTask(ThreadState* state, BaseHeap* heap, HeapStats* stats) 10629e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) : m_threadState(state) 10639e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) , m_heap(heap) 10649e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) , m_stats(stats) 10659e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) { 10669e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) m_threadState->registerSweepingTask(); 10679e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) } 10689e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) 10699e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) virtual ~SweepNonFinalizedHeapTask() 10709e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) { 10719e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) m_threadState->unregisterSweepingTask(); 10729e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) } 10739e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) 10749e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) virtual void run() { m_heap->sweep(m_stats); } 10759e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) 10769e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)private: 10779e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) ThreadState* m_threadState; 10789e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) BaseHeap* m_heap; 10799e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) HeapStats* m_stats; 10809e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)}; 10819e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) 108209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void ThreadState::performPendingSweep() 108309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 1084d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) if (!sweepRequested()) 1085d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) return; 1086d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 1087e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#if ENABLE(GC_PROFILE_HEAP) 1088e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) // We snapshot the heap prior to sweeping to get numbers for both resources 1089e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) // that have been allocated since the last GC and for resources that are 1090e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) // going to be freed. 1091e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) bool gcTracingEnabled; 1092e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) TRACE_EVENT_CATEGORY_GROUP_ENABLED("blink_gc", &gcTracingEnabled); 1093e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) if (gcTracingEnabled && m_stats.totalObjectSpace() > 0) 1094e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) snapshot(); 1095e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#endif 1096e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) 1097e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) TRACE_EVENT0("blink_gc", "ThreadState::performPendingSweep"); 1098197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 1099f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) double timeStamp = WTF::currentTimeMS(); 1100323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) const char* samplingState = TRACE_EVENT_GET_SAMPLING_STATE(); 1101c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (isMainThread()) { 1102c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) ScriptForbiddenScope::enter(); 1103197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch TRACE_EVENT_SET_SAMPLING_STATE("blink", "BlinkGCSweeping"); 1104c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) } 1105323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) 1106e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) size_t objectSpaceBeforeSweep = m_stats.totalObjectSpace(); 11077242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci { 11087242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci NoSweepScope scope(this); 11097242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 11107242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // Disallow allocation during weak processing. 11117242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci enterNoAllocationScope(); 11127242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci { 11137242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci TRACE_EVENT0("blink_gc", "ThreadState::threadLocalWeakProcessing"); 11147242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // Perform thread-specific weak processing. 11157242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci while (popAndInvokeWeakPointerCallback(Heap::s_markingVisitor)) { } 11167242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci } 11177242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci leaveNoAllocationScope(); 11187242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 11197242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // Perform sweeping and finalization. 11207242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 11217242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // Sweeping will recalculate the stats 11227242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci m_stats.clear(); 11237242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 11247242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // Sweep the non-finalized heap pages on multiple threads. 11257242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // Attempt to load-balance by having the sweeper thread sweep as 11267242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // close to half of the pages as possible. 11277242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci int nonFinalizedPages = 0; 11287242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci for (int i = 0; i < NumberOfNonFinalizedHeaps; i++) 11297242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci nonFinalizedPages += m_heaps[FirstNonFinalizedHeap + i]->normalPageCount(); 11307242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 11317242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci int finalizedPages = 0; 11327242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci for (int i = 0; i < NumberOfFinalizedHeaps; i++) 11337242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci finalizedPages += m_heaps[FirstFinalizedHeap + i]->normalPageCount(); 11347242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 11357242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci int pagesToSweepInParallel = nonFinalizedPages < finalizedPages ? nonFinalizedPages : ((nonFinalizedPages + finalizedPages) / 2); 11367242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 11377242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // Start the sweeper thread for the non finalized heaps. No 11387242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // finalizers need to run and therefore the pages can be 11397242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // swept on other threads. 11407242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci static const int minNumberOfPagesForParallelSweep = 10; 11417242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci HeapStats heapStatsVector[NumberOfNonFinalizedHeaps]; 11427242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci BaseHeap* splitOffHeaps[NumberOfNonFinalizedHeaps] = { 0 }; 11437242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci for (int i = 0; i < NumberOfNonFinalizedHeaps && pagesToSweepInParallel > 0; i++) { 11447242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci BaseHeap* heap = m_heaps[FirstNonFinalizedHeap + i]; 11457242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci int pageCount = heap->normalPageCount(); 11467242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // Only use the sweeper thread if it exists and there are 11477242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // pages to sweep. 11487242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci if (m_sweeperThread && pageCount > minNumberOfPagesForParallelSweep) { 11497242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // Create a new thread heap instance to make sure that the 11507242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // state modified while sweeping is separate for the 11517242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // sweeper thread and the owner thread. 11527242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci int pagesToSplitOff = std::min(pageCount, pagesToSweepInParallel); 11537242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci pagesToSweepInParallel -= pagesToSplitOff; 11547242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci BaseHeap* splitOff = heap->split(pagesToSplitOff); 11557242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci splitOffHeaps[i] = splitOff; 11567242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci HeapStats* stats = &heapStatsVector[i]; 11577242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci m_sweeperThread->postTask(new SweepNonFinalizedHeapTask(this, splitOff, stats)); 11587242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci } 11597242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci } 11609e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) 11617242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci { 11627242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // Sweep the remainder of the non-finalized pages (or all of them 11637242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // if there is no sweeper thread). 11647242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci TRACE_EVENT0("blink_gc", "ThreadState::sweepNonFinalizedHeaps"); 11657242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci for (int i = 0; i < NumberOfNonFinalizedHeaps; i++) { 11667242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci HeapStats stats; 11677242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci m_heaps[FirstNonFinalizedHeap + i]->sweep(&stats); 11687242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci m_stats.add(&stats); 11697242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci } 11709e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) } 11719e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) 11727242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci { 11737242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // Sweep the finalized pages. 11747242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci TRACE_EVENT0("blink_gc", "ThreadState::sweepFinalizedHeaps"); 11757242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci for (int i = 0; i < NumberOfFinalizedHeaps; i++) { 11767242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci HeapStats stats; 11777242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci m_heaps[FirstFinalizedHeap + i]->sweep(&stats); 11787242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci m_stats.add(&stats); 11797242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci } 11807242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci } 11819e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) 11827242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // Wait for the sweeper threads and update the heap stats with the 11837242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // stats for the heap portions swept by those threads. 11847242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci waitUntilSweepersDone(); 11857242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci for (int i = 0; i < NumberOfNonFinalizedHeaps; i++) { 11867242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci m_stats.add(&heapStatsVector[i]); 11877242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci if (BaseHeap* splitOff = splitOffHeaps[i]) 11887242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci m_heaps[FirstNonFinalizedHeap + i]->merge(splitOff); 11897242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci } 11909e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) 11917242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci for (int i = 0; i < NumberOfHeaps; i++) 11927242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci m_heaps[i]->postSweepProcessing(); 11939e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) 11947242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci getStats(m_statsAfterLastGC); 11959e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) 11967242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci } // End NoSweepScope 1197d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) clearGCRequested(); 1198d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) clearSweepRequested(); 1199e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) // If we collected less than 50% of objects, record that the 1200e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) // collection rate is low which we use to determine when to 1201e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) // perform the next GC. 1202e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) setLowCollectionRate(m_stats.totalObjectSpace() > (objectSpaceBeforeSweep >> 1)); 1203323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) 1204f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) if (blink::Platform::current()) { 1205f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) blink::Platform::current()->histogramCustomCounts("BlinkGC.PerformPendingSweep", WTF::currentTimeMS() - timeStamp, 0, 10 * 1000, 50); 1206f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) } 1207f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) 1208c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (isMainThread()) { 1209323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) TRACE_EVENT_SET_NONCONST_SAMPLING_STATE(samplingState); 1210c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) ScriptForbiddenScope::exit(); 1211c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) } 121209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 121309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 121409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void ThreadState::addInterruptor(Interruptor* interruptor) 121509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 121609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) SafePointScope scope(HeapPointersOnStack, SafePointScope::AllowNesting); 121709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 121809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) { 121909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) MutexLocker locker(threadAttachMutex()); 122009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) m_interruptors.append(interruptor); 122109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 122209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 122309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 122409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void ThreadState::removeInterruptor(Interruptor* interruptor) 122509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 122609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) SafePointScope scope(HeapPointersOnStack, SafePointScope::AllowNesting); 122709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 122809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) { 122909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) MutexLocker locker(threadAttachMutex()); 123009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) size_t index = m_interruptors.find(interruptor); 123109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) RELEASE_ASSERT(index >= 0); 123209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) m_interruptors.remove(index); 123309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 123409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 123509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 123609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void ThreadState::Interruptor::onInterrupted() 123709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 123809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ThreadState* state = ThreadState::current(); 123909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ASSERT(state); 124009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ASSERT(!state->isAtSafePoint()); 124109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) state->safePoint(HeapPointersOnStack); 124209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 124309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 124409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)ThreadState::AttachedThreadStateSet& ThreadState::attachedThreads() 124509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 124609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) DEFINE_STATIC_LOCAL(AttachedThreadStateSet, threads, ()); 124709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) return threads; 124809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 124909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 1250e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#if ENABLE(GC_PROFILE_MARKING) 12515d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)const GCInfo* ThreadState::findGCInfoFromAllThreads(Address address) 12525d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles){ 12535d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) bool needLockForIteration = !isAnyThreadInGC(); 12545d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) if (needLockForIteration) 12555d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) threadAttachMutex().lock(); 12565d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) 12575d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) ThreadState::AttachedThreadStateSet& threads = attachedThreads(); 12585d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end = threads.end(); it != end; ++it) { 12595d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) if (const GCInfo* gcInfo = (*it)->findGCInfo(address)) { 12605d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) if (needLockForIteration) 12615d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) threadAttachMutex().unlock(); 12625d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) return gcInfo; 12635d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) } 12645d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) } 12655d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) if (needLockForIteration) 12665d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) threadAttachMutex().unlock(); 12675d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) return 0; 12685d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)} 12695d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)#endif 1270e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) 127109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 1272