[K/N] Mark finalizing extra objects to avoid double finalizing
When new mark phase finished before previous finalization is done, extra objects are still in list, which would be passed to finalize. This could lead to unpredictable effects. After this commit such objects are marked by new flag and ignored by next gc runs.
This commit is contained in:
@@ -69,10 +69,11 @@ void SweepExtraObjects(typename Traits::ExtraObjectsFactory& objectFactory) noex
|
|||||||
auto iter = objectFactory.LockForIter();
|
auto iter = objectFactory.LockForIter();
|
||||||
for (auto it = iter.begin(); it != iter.end();) {
|
for (auto it = iter.begin(); it != iter.end();) {
|
||||||
auto &extraObject = *it;
|
auto &extraObject = *it;
|
||||||
if (!Traits::IsMarkedByExtraObject(extraObject)) {
|
if (!extraObject.getFlag(mm::ExtraObjectData::FLAGS_IN_FINALIZER_QUEUE) && !Traits::IsMarkedByExtraObject(extraObject)) {
|
||||||
extraObject.ClearWeakReferenceCounter();
|
extraObject.ClearWeakReferenceCounter();
|
||||||
if (extraObject.HasAssociatedObject()) {
|
if (extraObject.HasAssociatedObject()) {
|
||||||
extraObject.DetachAssociatedObject();
|
extraObject.DetachAssociatedObject();
|
||||||
|
extraObject.setFlag(mm::ExtraObjectData::FLAGS_IN_FINALIZER_QUEUE);
|
||||||
++it;
|
++it;
|
||||||
} else {
|
} else {
|
||||||
extraObject.Uninstall();
|
extraObject.Uninstall();
|
||||||
|
|||||||
@@ -23,10 +23,11 @@ namespace mm {
|
|||||||
// Optional data that's lazily allocated only for objects that need it.
|
// Optional data that's lazily allocated only for objects that need it.
|
||||||
class ExtraObjectData : private Pinned, public KonanAllocatorAware {
|
class ExtraObjectData : private Pinned, public KonanAllocatorAware {
|
||||||
public:
|
public:
|
||||||
|
// flags are stored as single atomic uint32, values are bit numbers in that uint32
|
||||||
enum Flags : uint32_t {
|
enum Flags : uint32_t {
|
||||||
FLAGS_NONE = 0,
|
FLAGS_FROZEN = 0,
|
||||||
FLAGS_FROZEN = 1 << 0,
|
FLAGS_NEVER_FROZEN = 1,
|
||||||
FLAGS_NEVER_FROZEN = 1 << 1,
|
FLAGS_IN_FINALIZER_QUEUE = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr unsigned WEAK_REF_TAG = 1;
|
static constexpr unsigned WEAK_REF_TAG = 1;
|
||||||
@@ -49,7 +50,9 @@ public:
|
|||||||
bool HasAssociatedObject() noexcept;
|
bool HasAssociatedObject() noexcept;
|
||||||
void DetachAssociatedObject() noexcept;
|
void DetachAssociatedObject() noexcept;
|
||||||
|
|
||||||
std::atomic<Flags>& flags() noexcept { return flags_; }
|
bool getFlag(Flags value) noexcept { return (flags_.load() & (1u << static_cast<uint32_t>(value))) != 0; }
|
||||||
|
void setFlag(Flags value) noexcept { flags_.fetch_or(1u << static_cast<uint32_t>(value)); }
|
||||||
|
|
||||||
|
|
||||||
bool HasWeakReferenceCounter() noexcept { return hasPointerBits(weakReferenceCounterOrBaseObject_.load(), WEAK_REF_TAG); }
|
bool HasWeakReferenceCounter() noexcept { return hasPointerBits(weakReferenceCounterOrBaseObject_.load(), WEAK_REF_TAG); }
|
||||||
void ClearWeakReferenceCounter() noexcept;
|
void ClearWeakReferenceCounter() noexcept;
|
||||||
@@ -84,7 +87,7 @@ private:
|
|||||||
// Must be first to match `TypeInfo` layout.
|
// Must be first to match `TypeInfo` layout.
|
||||||
const TypeInfo* typeInfo_;
|
const TypeInfo* typeInfo_;
|
||||||
|
|
||||||
std::atomic<Flags> flags_ = FLAGS_NONE;
|
std::atomic<uint32_t> flags_ = 0;
|
||||||
|
|
||||||
#ifdef KONAN_OBJC_INTEROP
|
#ifdef KONAN_OBJC_INTEROP
|
||||||
void* associatedObject_ = nullptr;
|
void* associatedObject_ = nullptr;
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ bool mm::IsFrozen(const ObjHeader* object) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (auto* extraObjectData = mm::ExtraObjectData::Get(object)) {
|
if (auto* extraObjectData = mm::ExtraObjectData::Get(object)) {
|
||||||
return (extraObjectData->flags() & mm::ExtraObjectData::FLAGS_FROZEN) != 0;
|
return extraObjectData->getFlag(mm::ExtraObjectData::FLAGS_FROZEN);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -48,12 +48,13 @@ ObjHeader* mm::FreezeSubgraph(ObjHeader* root) noexcept {
|
|||||||
}
|
}
|
||||||
for (auto* object : objects) {
|
for (auto* object : objects) {
|
||||||
if (auto* extraObjectData = mm::ExtraObjectData::Get(object)) {
|
if (auto* extraObjectData = mm::ExtraObjectData::Get(object)) {
|
||||||
if ((extraObjectData->flags() & mm::ExtraObjectData::FLAGS_NEVER_FROZEN) != 0) return object;
|
if (extraObjectData->getFlag(mm::ExtraObjectData::FLAGS_NEVER_FROZEN)) {
|
||||||
|
return object;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (auto* object : objects) {
|
for (auto* object : objects) {
|
||||||
auto& flags = mm::ExtraObjectData::GetOrInstall(object).flags();
|
mm::ExtraObjectData::GetOrInstall(object).setFlag(mm::ExtraObjectData::FLAGS_FROZEN);
|
||||||
flags = static_cast<mm::ExtraObjectData::Flags>(flags | mm::ExtraObjectData::FLAGS_FROZEN);
|
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -63,7 +64,6 @@ bool mm::EnsureNeverFrozen(ObjHeader* object) noexcept {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& flags = mm::ExtraObjectData::GetOrInstall(object).flags();
|
mm::ExtraObjectData::GetOrInstall(object).setFlag(mm::ExtraObjectData::FLAGS_NEVER_FROZEN);
|
||||||
flags = static_cast<mm::ExtraObjectData::Flags>(flags | mm::ExtraObjectData::FLAGS_NEVER_FROZEN);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user