Native: don't dispatch release for null Obj-C refs to the main thread

Currently, if a Kotlin object happens to have null for an associated
object but FLAGS_RELEASE_ON_MAIN_QUEUE flag set, GC will dispatch
Kotlin_ObjCExport_releaseAssociatedObject(null) to the main thread
anyway.

This couldn't happen before, but can now, with disposeObjCObject.
The commit prevents this, by moving the null check out from
Kotlin_ObjCExport_releaseAssociatedObject to call sites.

^KT-59134
This commit is contained in:
Svyatoslav Scherbina
2023-06-05 17:48:09 +02:00
committed by Space Team
parent 1bf3d55bdf
commit 063e7258ee
3 changed files with 16 additions and 13 deletions
@@ -3085,7 +3085,9 @@ void ObjHeader::destroyMetaObject(ObjHeader* object) {
}
#ifdef KONAN_OBJC_INTEROP
Kotlin_ObjCExport_releaseAssociatedObject(meta->associatedObject_);
if (void* associatedObject = meta->associatedObject_) {
Kotlin_ObjCExport_releaseAssociatedObject(associatedObject);
}
#endif
std_support::allocator_delete(objectAllocator, meta);
@@ -107,11 +107,10 @@ ALWAYS_INLINE void send_releaseAsAssociatedObject(void* associatedObject) {
} // namespace
extern "C" ALWAYS_INLINE void Kotlin_ObjCExport_releaseAssociatedObject(void* associatedObject) {
if (associatedObject != nullptr) {
// May already be in the native state if was scheduled on the main queue.
NativeOrUnregisteredThreadGuard guard(/*reentrant=*/ true);
send_releaseAsAssociatedObject(associatedObject);
}
RuntimeAssert(associatedObject != nullptr, "Kotlin_ObjCExport_releaseAssociatedObject(nullptr)");
// May already be in the native state if was scheduled on the main queue.
NativeOrUnregisteredThreadGuard guard(/*reentrant=*/ true);
send_releaseAsAssociatedObject(associatedObject);
}
extern "C" id Kotlin_ObjCExport_convertUnitToRetained(ObjHeader* unitInstance) {
@@ -60,14 +60,16 @@ void mm::ExtraObjectData::Uninstall() noexcept {
this);
#ifdef KONAN_OBJC_INTEROP
if (getFlag(FLAGS_RELEASE_ON_MAIN_QUEUE) && isMainQueueProcessorAvailable()) {
runOnMainQueue(associatedObject_, [](void* obj) {
Kotlin_ObjCExport_releaseAssociatedObject(obj);
});
} else {
Kotlin_ObjCExport_releaseAssociatedObject(associatedObject_);
if (void* associatedObject = associatedObject_) {
if (getFlag(FLAGS_RELEASE_ON_MAIN_QUEUE) && isMainQueueProcessorAvailable()) {
runOnMainQueue(associatedObject, [](void* obj) {
Kotlin_ObjCExport_releaseAssociatedObject(obj);
});
} else {
Kotlin_ObjCExport_releaseAssociatedObject(associatedObject);
}
associatedObject_ = nullptr;
}
associatedObject_ = nullptr;
#endif
}