blob: 22dba9a5461924fbdd4698335a4e6380a5146834 [file]
/*
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
#ifndef RUNTIME_MM_THREAD_DATA_H
#define RUNTIME_MM_THREAD_DATA_H
#include <atomic>
#include "GlobalData.hpp"
#include "GlobalsRegistry.hpp"
#include "GC.hpp"
#include "GCScheduler.hpp"
#include "ObjectFactory.hpp"
#include "ExtraObjectDataFactory.hpp"
#include "ShadowStack.hpp"
#include "SpecialRefRegistry.hpp"
#include "ThreadLocalStorage.hpp"
#include "Utils.hpp"
#include "ThreadSuspension.hpp"
#include "std_support/Vector.hpp"
struct ObjHeader;
namespace kotlin {
namespace mm {
// `ThreadData` is supposed to be thread local singleton.
// Pin it in memory to prevent accidental copying.
class ThreadData final : private Pinned {
public:
explicit ThreadData(int threadId) noexcept :
threadId_(threadId),
globalsThreadQueue_(GlobalsRegistry::Instance()),
specialRefRegistry_(SpecialRefRegistry::instance()),
#ifndef CUSTOM_ALLOCATOR
extraObjectDataThreadQueue_(ExtraObjectDataFactory::Instance()),
#endif
gc_(GlobalData::Instance().gc(), *this),
suspensionData_(ThreadState::kNative, *this) {}
~ThreadData() = default;
int threadId() const noexcept { return threadId_; }
GlobalsRegistry::ThreadQueue& globalsThreadQueue() noexcept { return globalsThreadQueue_; }
ThreadLocalStorage& tls() noexcept { return tls_; }
SpecialRefRegistry::ThreadQueue& specialRefRegistry() noexcept { return specialRefRegistry_; }
#ifndef CUSTOM_ALLOCATOR
ExtraObjectDataFactory::ThreadQueue& extraObjectDataThreadQueue() noexcept { return extraObjectDataThreadQueue_; }
#endif
ThreadState state() noexcept { return suspensionData_.state(); }
ThreadState setState(ThreadState state) noexcept { return suspensionData_.setState(state); }
ShadowStack& shadowStack() noexcept { return shadowStack_; }
std_support::vector<std::pair<ObjHeader**, ObjHeader*>>& initializingSingletons() noexcept { return initializingSingletons_; }
gc::GC::ThreadData& gc() noexcept { return gc_; }
ThreadSuspensionData& suspensionData() { return suspensionData_; }
void Publish() noexcept {
// TODO: These use separate locks, which is inefficient.
globalsThreadQueue_.Publish();
specialRefRegistry_.publish();
#ifndef CUSTOM_ALLOCATOR
extraObjectDataThreadQueue_.Publish();
#endif
gc_.Publish();
}
void ClearForTests() noexcept {
globalsThreadQueue_.ClearForTests();
specialRefRegistry_.clearForTests();
#ifndef CUSTOM_ALLOCATOR
extraObjectDataThreadQueue_.ClearForTests();
#endif
gc_.ClearForTests();
}
private:
const int threadId_;
GlobalsRegistry::ThreadQueue globalsThreadQueue_;
ThreadLocalStorage tls_;
SpecialRefRegistry::ThreadQueue specialRefRegistry_;
#ifndef CUSTOM_ALLOCATOR
ExtraObjectDataFactory::ThreadQueue extraObjectDataThreadQueue_;
#endif
ShadowStack shadowStack_;
gc::GC::ThreadData gc_;
std_support::vector<std::pair<ObjHeader**, ObjHeader*>> initializingSingletons_;
ThreadSuspensionData suspensionData_;
};
} // namespace mm
} // namespace kotlin
#endif // RUNTIME_MM_THREAD_DATA_H