#ifndef ThreadState_h
#define ThreadState_h
+#include "heap/AddressSanitizer.h"
#include "heap/HeapExport.h"
#include "wtf/HashSet.h"
+#include "wtf/OwnPtr.h"
+#include "wtf/PassOwnPtr.h"
#include "wtf/ThreadSpecific.h"
#include "wtf/Threading.h"
+#include "wtf/ThreadingPrimitives.h"
#include "wtf/Vector.h"
namespace WebCore {
};
class HEAP_EXPORT ThreadState {
+ WTF_MAKE_NONCOPYABLE(ThreadState);
public:
// When garbage collecting we need to know whether or not there
// can be pointers to Blink GC managed objects on the stack for
// It also has to periodically check for safepoints.
static void attach();
+ // When ThreadState is detaching from non-main thread its
+ // heap is expected to be empty (because it is going away).
+ // Perform registered cleanup tasks and garbage collection
+ // to sweep away any objects that are left on this heap.
+ // We assert that nothing must remain after this cleanup.
+ // If assertion does not hold we crash as we are potentially
+ // in the dangling pointer situation.
+ void cleanup();
+
// Disassociate attached ThreadState from the current thread. The thread
// can no longer use the garbage collected heap after this call.
static void detach();
// can provide an interruptor object which would allow GC
// to temporarily interrupt and pause this long running loop at
// an arbitrary moment creating a safepoint for a GC.
- class Interruptor {
+ class HEAP_EXPORT Interruptor {
public:
virtual ~Interruptor() { }
void addInterruptor(Interruptor*);
void removeInterruptor(Interruptor*);
+ // CleanupTasks are executed when ThreadState performs
+ // cleanup before detaching.
+ class CleanupTask {
+ public:
+ virtual ~CleanupTask() { }
+
+ // Executed before the final GC.
+ virtual void preCleanup() { }
+
+ // Executed after the final GC. Thread heap is empty at this point.
+ virtual void postCleanup() { }
+ };
+
+ void addCleanupTask(PassOwnPtr<CleanupTask> cleanupTask)
+ {
+ m_cleanupTasks.append(cleanupTask);
+ }
+
// Should only be called under protection of threadAttachMutex().
const Vector<Interruptor*>& interruptors() const { return m_interruptors; }
// List of persistent roots allocated on the given thread.
PersistentNode* roots() const { return m_persistents; }
+ // List of global persistent roots not owned by any particular thread.
+ // globalRootsMutex must be acquired before any modifications.
+ static PersistentNode* globalRoots();
+ static Mutex& globalRootsMutex();
+
// Visit local thread stack and trace all pointers conservatively.
void visitStack(Visitor*);
friend class SafePointBarrier;
void enterSafePoint(StackState, void*);
- void copyStackUntilSafePointScope();
+ NO_SANITIZE_ADDRESS void copyStackUntilSafePointScope();
void clearSafePointScopeMarker()
{
m_safePointStackCopy.clear();
HeapContainsCache* m_heapContainsCache;
HeapStats m_stats;
HeapStats m_statsAfterLastGC;
+
+ Vector<OwnPtr<CleanupTask> > m_cleanupTasks;
+ bool m_isCleaningUp;
};
template<ThreadAffinity affinity> class ThreadStateFor;
static ThreadState* state() { return ThreadState::current(); }
};
+// FIXME: Experiment if the threading affinity really matters for performance.
+// FIXME: Move these macros and other related structures to a separate file.
+USED_FROM_MULTIPLE_THREADS(Algorithm);
+USED_FROM_MULTIPLE_THREADS(Crypto);
+USED_FROM_MULTIPLE_THREADS(DeprecatedStorageQuota);
+USED_FROM_MULTIPLE_THREADS(Key);
+USED_FROM_MULTIPLE_THREADS(KeyPair);
+USED_FROM_MULTIPLE_THREADS(Notification);
+USED_FROM_MULTIPLE_THREADS(NotificationCenter);
+USED_FROM_MULTIPLE_THREADS(SubtleCrypto);
+USED_FROM_MULTIPLE_THREADS(TextDecoder);
+USED_FROM_MULTIPLE_THREADS(TextEncoder);
+USED_FROM_MULTIPLE_THREADS(WebKitNotification);
+USED_FROM_MULTIPLE_THREADS(WorkerCrypto);
+USED_FROM_MULTIPLE_THREADS(WorkerPerformance);
+
}
#endif // ThreadState_h