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