[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_);
|
||||
}
|
||||
|
||||
void BackRefFromAssociatedObject::initForPermanentObject(ObjHeader* obj) {
|
||||
initAndAddRef(obj);
|
||||
}
|
||||
|
||||
void BackRefFromAssociatedObject::initAndAddRef(ObjHeader* obj) {
|
||||
RuntimeAssert(obj != nullptr, "must not be null");
|
||||
obj_ = obj;
|
||||
@@ -198,3 +202,7 @@ ObjHeader* BackRefFromAssociatedObject::ref() const {
|
||||
template ObjHeader* BackRefFromAssociatedObject::ref<ErrorPolicy::kDefaultValue>() const;
|
||||
template ObjHeader* BackRefFromAssociatedObject::ref<ErrorPolicy::kThrow>() 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 {
|
||||
public:
|
||||
void initForPermanentObject(ObjHeader* obj);
|
||||
void initAndAddRef(ObjHeader* 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>
|
||||
ObjHeader* ref() const;
|
||||
|
||||
ObjHeader* refPermanent() const;
|
||||
|
||||
private:
|
||||
ObjHeader* obj_; // May be null before [initAndAddRef] or after [detach].
|
||||
ForeignRefContext context_;
|
||||
|
||||
@@ -41,8 +41,15 @@ void KRefSharedHolder::dispose() {
|
||||
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) {
|
||||
RuntimeAssert(obj != nullptr, "must not be null");
|
||||
RuntimeAssert(!obj->permanent(), "Can only be called with non-permanent object");
|
||||
obj_ = obj;
|
||||
|
||||
// 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::kThrow>() 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 {
|
||||
RETURN_OBJ(refHolder.ref<ErrorPolicy::kTerminate>());
|
||||
if (permanent) {
|
||||
RETURN_OBJ(refHolder.refPermanent());
|
||||
} else {
|
||||
RETURN_OBJ(refHolder.ref<ErrorPolicy::kTerminate>());
|
||||
}
|
||||
}
|
||||
|
||||
+(void)load {
|
||||
@@ -88,10 +92,11 @@ static void injectToRuntime();
|
||||
|
||||
KotlinBase* candidate = [super allocWithZone:nil];
|
||||
// TODO: should we call NSObject.init ?
|
||||
candidate->refHolder.initAndAddRef(obj);
|
||||
candidate->permanent = obj->permanent();
|
||||
bool 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)) {
|
||||
SetAssociatedObject(obj, candidate);
|
||||
} else {
|
||||
@@ -105,6 +110,8 @@ static void injectToRuntime();
|
||||
return objc_retain(old);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
candidate->refHolder.initForPermanentObject(obj);
|
||||
}
|
||||
|
||||
return candidate;
|
||||
@@ -136,6 +143,8 @@ static void injectToRuntime();
|
||||
}
|
||||
|
||||
-(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
|
||||
// deallocation hooks at the moment, including deallocation of the "associated object" ([self])
|
||||
// using the [super release] call below.
|
||||
|
||||
Reference in New Issue
Block a user