[K/N] Handle permanent objects in new MM MemorySharedRefs ^KT-56233
Do not create a foreign ref to the permanent objects. There's no need to do it, and, moreover, this ref would have leaked.
This commit is contained in:
committed by
Space Team
parent
1f1b26f2a5
commit
8a8aeed998
@@ -104,6 +104,10 @@ void KRefSharedHolder::dispose() {
|
|||||||
DeinitForeignRef(obj_, context_);
|
DeinitForeignRef(obj_, context_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BackRefFromAssociatedObject::initForPermanentObject(ObjHeader* obj) {
|
||||||
|
initAndAddRef(obj);
|
||||||
|
}
|
||||||
|
|
||||||
void BackRefFromAssociatedObject::initAndAddRef(ObjHeader* obj) {
|
void BackRefFromAssociatedObject::initAndAddRef(ObjHeader* obj) {
|
||||||
RuntimeAssert(obj != nullptr, "must not be null");
|
RuntimeAssert(obj != nullptr, "must not be null");
|
||||||
obj_ = obj;
|
obj_ = obj;
|
||||||
@@ -198,3 +202,7 @@ ObjHeader* BackRefFromAssociatedObject::ref() const {
|
|||||||
template ObjHeader* BackRefFromAssociatedObject::ref<ErrorPolicy::kDefaultValue>() const;
|
template ObjHeader* BackRefFromAssociatedObject::ref<ErrorPolicy::kDefaultValue>() const;
|
||||||
template ObjHeader* BackRefFromAssociatedObject::ref<ErrorPolicy::kThrow>() const;
|
template ObjHeader* BackRefFromAssociatedObject::ref<ErrorPolicy::kThrow>() const;
|
||||||
template ObjHeader* BackRefFromAssociatedObject::ref<ErrorPolicy::kTerminate>() const;
|
template ObjHeader* BackRefFromAssociatedObject::ref<ErrorPolicy::kTerminate>() const;
|
||||||
|
|
||||||
|
ObjHeader* BackRefFromAssociatedObject::refPermanent() const {
|
||||||
|
return ref<ErrorPolicy::kIgnore>();
|
||||||
|
}
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ static_assert(std::is_trivially_destructible_v<KRefSharedHolder>, "KRefSharedHol
|
|||||||
|
|
||||||
class BackRefFromAssociatedObject {
|
class BackRefFromAssociatedObject {
|
||||||
public:
|
public:
|
||||||
|
void initForPermanentObject(ObjHeader* obj);
|
||||||
void initAndAddRef(ObjHeader* obj);
|
void initAndAddRef(ObjHeader* obj);
|
||||||
|
|
||||||
// Error if refCount is zero and it's called from the wrong worker with non-frozen obj_.
|
// Error if refCount is zero and it's called from the wrong worker with non-frozen obj_.
|
||||||
@@ -65,6 +66,8 @@ class BackRefFromAssociatedObject {
|
|||||||
template <ErrorPolicy errorPolicy>
|
template <ErrorPolicy errorPolicy>
|
||||||
ObjHeader* ref() const;
|
ObjHeader* ref() const;
|
||||||
|
|
||||||
|
ObjHeader* refPermanent() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ObjHeader* obj_; // May be null before [initAndAddRef] or after [detach].
|
ObjHeader* obj_; // May be null before [initAndAddRef] or after [detach].
|
||||||
ForeignRefContext context_;
|
ForeignRefContext context_;
|
||||||
|
|||||||
@@ -41,8 +41,15 @@ void KRefSharedHolder::dispose() {
|
|||||||
DeinitForeignRef(obj_, context_);
|
DeinitForeignRef(obj_, context_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BackRefFromAssociatedObject::initForPermanentObject(ObjHeader* obj) {
|
||||||
|
RuntimeAssert(obj != nullptr, "must not be null");
|
||||||
|
RuntimeAssert(obj->permanent(), "Can only be called with permanent object");
|
||||||
|
obj_ = obj;
|
||||||
|
}
|
||||||
|
|
||||||
void BackRefFromAssociatedObject::initAndAddRef(ObjHeader* obj) {
|
void BackRefFromAssociatedObject::initAndAddRef(ObjHeader* obj) {
|
||||||
RuntimeAssert(obj != nullptr, "must not be null");
|
RuntimeAssert(obj != nullptr, "must not be null");
|
||||||
|
RuntimeAssert(!obj->permanent(), "Can only be called with non-permanent object");
|
||||||
obj_ = obj;
|
obj_ = obj;
|
||||||
|
|
||||||
// Generally a specialized addRef below:
|
// Generally a specialized addRef below:
|
||||||
@@ -126,3 +133,7 @@ ObjHeader* BackRefFromAssociatedObject::ref() const {
|
|||||||
template ObjHeader* BackRefFromAssociatedObject::ref<ErrorPolicy::kDefaultValue>() const;
|
template ObjHeader* BackRefFromAssociatedObject::ref<ErrorPolicy::kDefaultValue>() const;
|
||||||
template ObjHeader* BackRefFromAssociatedObject::ref<ErrorPolicy::kThrow>() const;
|
template ObjHeader* BackRefFromAssociatedObject::ref<ErrorPolicy::kThrow>() const;
|
||||||
template ObjHeader* BackRefFromAssociatedObject::ref<ErrorPolicy::kTerminate>() const;
|
template ObjHeader* BackRefFromAssociatedObject::ref<ErrorPolicy::kTerminate>() const;
|
||||||
|
|
||||||
|
ObjHeader* BackRefFromAssociatedObject::refPermanent() const {
|
||||||
|
return obj_;
|
||||||
|
}
|
||||||
|
|||||||
@@ -42,7 +42,11 @@ static void injectToRuntime();
|
|||||||
}
|
}
|
||||||
|
|
||||||
-(KRef)toKotlin:(KRef*)OBJ_RESULT {
|
-(KRef)toKotlin:(KRef*)OBJ_RESULT {
|
||||||
RETURN_OBJ(refHolder.ref<ErrorPolicy::kTerminate>());
|
if (permanent) {
|
||||||
|
RETURN_OBJ(refHolder.refPermanent());
|
||||||
|
} else {
|
||||||
|
RETURN_OBJ(refHolder.ref<ErrorPolicy::kTerminate>());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
+(void)load {
|
+(void)load {
|
||||||
@@ -88,10 +92,11 @@ static void injectToRuntime();
|
|||||||
|
|
||||||
KotlinBase* candidate = [super allocWithZone:nil];
|
KotlinBase* candidate = [super allocWithZone:nil];
|
||||||
// TODO: should we call NSObject.init ?
|
// TODO: should we call NSObject.init ?
|
||||||
candidate->refHolder.initAndAddRef(obj);
|
bool permanent = obj->permanent();
|
||||||
candidate->permanent = obj->permanent();
|
candidate->permanent = permanent;
|
||||||
|
|
||||||
if (!obj->permanent()) { // TODO: permanent objects should probably be supported as custom types.
|
if (!permanent) { // TODO: permanent objects should probably be supported as custom types.
|
||||||
|
candidate->refHolder.initAndAddRef(obj);
|
||||||
if (!isShareable(obj)) {
|
if (!isShareable(obj)) {
|
||||||
SetAssociatedObject(obj, candidate);
|
SetAssociatedObject(obj, candidate);
|
||||||
} else {
|
} else {
|
||||||
@@ -105,6 +110,8 @@ static void injectToRuntime();
|
|||||||
return objc_retain(old);
|
return objc_retain(old);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
candidate->refHolder.initForPermanentObject(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
return candidate;
|
return candidate;
|
||||||
@@ -136,6 +143,8 @@ static void injectToRuntime();
|
|||||||
}
|
}
|
||||||
|
|
||||||
-(void)releaseAsAssociatedObject:(ReleaseMode)mode {
|
-(void)releaseAsAssociatedObject:(ReleaseMode)mode {
|
||||||
|
RuntimeAssert(!permanent, "Cannot be called on permanent objects");
|
||||||
|
|
||||||
// This function is called by the GC. It made a decision to reclaim Kotlin object, and runs
|
// This function is called by the GC. It made a decision to reclaim Kotlin object, and runs
|
||||||
// deallocation hooks at the moment, including deallocation of the "associated object" ([self])
|
// deallocation hooks at the moment, including deallocation of the "associated object" ([self])
|
||||||
// using the [super release] call below.
|
// using the [super release] call below.
|
||||||
|
|||||||
Reference in New Issue
Block a user