[K/N] Fix a race in MemorySharedRefs ^KT-56233
This commit is contained in:
committed by
Space Team
parent
8a8aeed998
commit
4cd1f2ff82
@@ -16,7 +16,7 @@
|
||||
#include "ObjectOps.hpp"
|
||||
#include "Porting.h"
|
||||
#include "Runtime.h"
|
||||
#include "StableRefRegistry.hpp"
|
||||
#include "StableRef.hpp"
|
||||
#include "ThreadData.hpp"
|
||||
#include "ThreadRegistry.hpp"
|
||||
#include "ThreadState.hpp"
|
||||
@@ -24,29 +24,6 @@
|
||||
|
||||
using namespace kotlin;
|
||||
|
||||
// TODO: This name does not make sense anymore.
|
||||
// Delete all means of creating this type directly as it only serves
|
||||
// as a typedef for `mm::StableRefRegistry::Node`.
|
||||
class ForeignRefManager : Pinned {
|
||||
public:
|
||||
ForeignRefManager() = delete;
|
||||
~ForeignRefManager() = delete;
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
||||
// `reinterpret_cast` to it and back to the same type
|
||||
// will yield precisely the same pointer, so it's safe.
|
||||
ALWAYS_INLINE ForeignRefManager* ToForeignRefManager(mm::StableRefRegistry::Node* data) {
|
||||
return reinterpret_cast<ForeignRefManager*>(data);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE mm::StableRefRegistry::Node* FromForeignRefManager(ForeignRefManager* manager) {
|
||||
return reinterpret_cast<mm::StableRefRegistry::Node*>(manager);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
ObjHeader* ObjHeader::GetWeakCounter() {
|
||||
RuntimeFail("Only for legacy MM");
|
||||
}
|
||||
@@ -464,16 +441,6 @@ extern "C" RUNTIME_NOTHROW void PerformFullGC(MemoryState* memory) {
|
||||
threadData->gc().ScheduleAndWaitFullGCWithFinalizers();
|
||||
}
|
||||
|
||||
extern "C" RUNTIME_NOTHROW OBJ_GETTER(TryRef, ObjHeader* object) {
|
||||
// TODO: With CMS this needs:
|
||||
// * during marking phase if `object` is unmarked: barrier (might be automatic because of the stack write)
|
||||
// and return `object`;
|
||||
// * during marking phase if `object` is marked: return `object`;
|
||||
// * during sweeping phase if `object` is unmarked: return nullptr;
|
||||
// * during sweeping phase if `object` is marked: return `object`;
|
||||
RETURN_OBJ(object);
|
||||
}
|
||||
|
||||
extern "C" RUNTIME_NOTHROW bool ClearSubgraphReferences(ObjHeader* root, bool checked) {
|
||||
// TODO: Remove when legacy MM is gone.
|
||||
return true;
|
||||
@@ -483,24 +450,23 @@ extern "C" RUNTIME_NOTHROW void* CreateStablePointer(ObjHeader* object) {
|
||||
if (!object)
|
||||
return nullptr;
|
||||
|
||||
auto* threadData = mm::ThreadRegistry::Instance().CurrentThreadData();
|
||||
AssertThreadState(threadData, ThreadState::kRunnable);
|
||||
return mm::StableRefRegistry::Instance().RegisterStableRef(threadData, object);
|
||||
AssertThreadState(ThreadState::kRunnable);
|
||||
return static_cast<mm::RawSpecialRef*>(mm::StableRef::create(object));
|
||||
}
|
||||
|
||||
extern "C" RUNTIME_NOTHROW void DisposeStablePointer(void* pointer) {
|
||||
DisposeStablePointerFor(kotlin::mm::GetMemoryState(), pointer);
|
||||
if (!pointer) return;
|
||||
|
||||
// Can be safely called in any thread state.
|
||||
mm::StableRef(static_cast<mm::RawSpecialRef*>(pointer)).dispose();
|
||||
}
|
||||
|
||||
extern "C" RUNTIME_NOTHROW void DisposeStablePointerFor(MemoryState* memoryState, void* pointer) {
|
||||
if (!pointer)
|
||||
return;
|
||||
|
||||
auto* threadData = memoryState->GetThreadData();
|
||||
AssertThreadState(threadData, ThreadState::kRunnable);
|
||||
|
||||
auto* node = static_cast<mm::StableRefRegistry::Node*>(pointer);
|
||||
mm::StableRefRegistry::Instance().UnregisterStableRef(threadData, node);
|
||||
// Can be safely called in any thread state.
|
||||
mm::StableRef(static_cast<mm::RawSpecialRef*>(pointer)).disposeOn(*mm::FromMemoryState(memoryState)->Get());
|
||||
}
|
||||
|
||||
extern "C" RUNTIME_NOTHROW OBJ_GETTER(DerefStablePointer, void* pointer) {
|
||||
@@ -508,24 +474,19 @@ extern "C" RUNTIME_NOTHROW OBJ_GETTER(DerefStablePointer, void* pointer) {
|
||||
RETURN_OBJ(nullptr);
|
||||
|
||||
AssertThreadState(ThreadState::kRunnable);
|
||||
|
||||
auto* node = static_cast<mm::StableRefRegistry::Node*>(pointer);
|
||||
ObjHeader* object = **node;
|
||||
RETURN_OBJ(object);
|
||||
RETURN_OBJ(*mm::StableRef(static_cast<mm::RawSpecialRef*>(pointer)));
|
||||
}
|
||||
|
||||
extern "C" RUNTIME_NOTHROW OBJ_GETTER(AdoptStablePointer, void* pointer) {
|
||||
if (!pointer)
|
||||
RETURN_OBJ(nullptr);
|
||||
|
||||
auto* threadData = mm::ThreadRegistry::Instance().CurrentThreadData();
|
||||
AssertThreadState(threadData, ThreadState::kRunnable);
|
||||
auto* node = static_cast<mm::StableRefRegistry::Node*>(pointer);
|
||||
ObjHeader* object = **node;
|
||||
// Make sure `object` stays in the rootset: put it on the stack before removing it from `StableRefRegistry`.
|
||||
mm::SetStackRef(OBJ_RESULT, object);
|
||||
mm::StableRefRegistry::Instance().UnregisterStableRef(threadData, node);
|
||||
return object;
|
||||
AssertThreadState(ThreadState::kRunnable);
|
||||
mm::StableRef stableRef(static_cast<mm::RawSpecialRef*>(pointer));
|
||||
auto* obj = *stableRef;
|
||||
mm::SetStackRef(OBJ_RESULT, obj);
|
||||
std::move(stableRef).dispose();
|
||||
return obj;
|
||||
}
|
||||
|
||||
extern "C" void MutationCheck(ObjHeader* obj) {
|
||||
@@ -554,22 +515,6 @@ extern "C" void EnsureNeverFrozen(ObjHeader* obj) {
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" ForeignRefContext InitForeignRef(ObjHeader* object) {
|
||||
AssertThreadState(ThreadState::kRunnable);
|
||||
auto* threadData = mm::ThreadRegistry::Instance().CurrentThreadData();
|
||||
auto* node = mm::StableRefRegistry::Instance().RegisterStableRef(threadData, object);
|
||||
return ToForeignRefManager(node);
|
||||
}
|
||||
|
||||
extern "C" void DeinitForeignRef(ObjHeader* object, ForeignRefContext context) {
|
||||
AssertThreadState(ThreadState::kRunnable);
|
||||
RuntimeAssert(context != nullptr, "DeinitForeignRef must not be called for InitLocalForeignRef");
|
||||
auto* threadData = mm::ThreadRegistry::Instance().CurrentThreadData();
|
||||
auto* node = FromForeignRefManager(context);
|
||||
RuntimeAssert(object == **node, "Must correspond to the same object");
|
||||
mm::StableRefRegistry::Instance().UnregisterStableRef(threadData, node);
|
||||
}
|
||||
|
||||
extern "C" void CheckGlobalsAccessible() {
|
||||
// TODO: Remove when legacy MM is gone.
|
||||
// Always accessible
|
||||
@@ -659,3 +604,7 @@ RUNTIME_NOTHROW extern "C" OBJ_GETTER(Konan_WeakReferenceCounterLegacyMM_get, Ob
|
||||
RUNTIME_NOTHROW extern "C" OBJ_GETTER(Konan_RegularWeakReferenceImpl_get, ObjHeader* weakRef) {
|
||||
RETURN_RESULT_OF(mm::derefRegularWeakReferenceImpl, weakRef);
|
||||
}
|
||||
|
||||
RUNTIME_NOTHROW extern "C" void DisposeRegularWeakReferenceImpl(ObjHeader* weakRef) {
|
||||
mm::disposeRegularWeakReferenceImpl(weakRef);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user