Use meta object for storing associated Objective-C object
This commit is contained in:
committed by
SvyatoslavScherbina
parent
841bb51e65
commit
38f896649c
-9
@@ -431,15 +431,6 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) {
|
||||
val Kotlin_ObjCExport_RethrowExceptionAsNSError by lazyRtFunction
|
||||
val Kotlin_ObjCExport_RethrowNSErrorAsException by lazyRtFunction
|
||||
|
||||
val kObjectReservedTailSize = if (context.config.produce.isNativeBinary) {
|
||||
// Note: this defines the global declared in runtime (if any).
|
||||
staticData.placeGlobal("kObjectReservedTailSize", Int32(0), isExported = true).also {
|
||||
it.setConstant(true)
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
val objCExportEnabled = if (context.config.produce.isNativeBinary) {
|
||||
// Note: this defines the global declared in runtime (if any).
|
||||
staticData.placeGlobal("objCExportEnabled", Int8(0), isExported = true).also {
|
||||
|
||||
-1
@@ -217,7 +217,6 @@ internal class ObjCExportCodeGenerator(
|
||||
emitSortedAdapters(placedClassAdapters, "Kotlin_ObjCExport_sortedClassAdapters")
|
||||
emitSortedAdapters(placedInterfaceAdapters, "Kotlin_ObjCExport_sortedProtocolAdapters")
|
||||
|
||||
context.llvm.kObjectReservedTailSize!!.setInitializer(Int32(runtime.pointerSize))
|
||||
context.llvm.objCExportEnabled!!.setInitializer(Int8(1))
|
||||
|
||||
dataGenerator.finishModule() // TODO: move to appropriate place.
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
#if KONAN_OBJC_INTEROP
|
||||
#define KONAN_OBJECTS_CAN_HAVE_RESERVED_TAIL 1
|
||||
#define KONAN_TYPE_INFO_HAS_WRITABLE_PART 1
|
||||
#endif
|
||||
|
||||
|
||||
@@ -376,17 +376,10 @@ inline container_size_t alignUp(container_size_t size, int alignment) {
|
||||
return (size + alignment - 1) & ~(alignment - 1);
|
||||
}
|
||||
|
||||
#if KONAN_OBJECTS_CAN_HAVE_RESERVED_TAIL
|
||||
// Note: defined by a compiler-generated bitcode.
|
||||
extern "C" const container_size_t kObjectReservedTailSize;
|
||||
#else
|
||||
constexpr container_size_t kObjectReservedTailSize = 0;
|
||||
#endif
|
||||
|
||||
// TODO: shall we do padding for alignment?
|
||||
inline container_size_t objectSize(const ObjHeader* obj) {
|
||||
const TypeInfo* type_info = obj->type_info();
|
||||
container_size_t size = kObjectReservedTailSize + (type_info->instanceSize_ < 0 ?
|
||||
container_size_t size = (type_info->instanceSize_ < 0 ?
|
||||
// An array.
|
||||
ArrayDataSizeBytes(obj->array()) + sizeof(ArrayHeader)
|
||||
:
|
||||
@@ -415,7 +408,7 @@ inline bool isRefCounted(KConstRef object) {
|
||||
extern "C" {
|
||||
|
||||
void objc_release(void* ptr);
|
||||
void Kotlin_ObjCExport_releaseReservedObjectTail(ObjHeader* obj);
|
||||
void Kotlin_ObjCExport_releaseAssociatedObject(void* associatedObject);
|
||||
RUNTIME_NORETURN void ThrowFreezingException();
|
||||
RUNTIME_NORETURN void ThrowInvalidMutabilityException();
|
||||
|
||||
@@ -426,14 +419,9 @@ inline void runDeallocationHooks(ObjHeader* obj) {
|
||||
ObjHeader::destroyMetaObject(&obj->typeInfoOrMeta_);
|
||||
}
|
||||
#if KONAN_OBJC_INTEROP
|
||||
// TODO: rewrite using meta-object.
|
||||
if (obj->type_info() == theObjCPointerHolderTypeInfo) {
|
||||
void* objcPtr = *reinterpret_cast<void**>(obj + 1); // TODO: use more reliable layout description
|
||||
objc_release(objcPtr);
|
||||
} else {
|
||||
if (HasReservedObjectTail(obj)) {
|
||||
Kotlin_ObjCExport_releaseReservedObjectTail(obj);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -838,6 +826,11 @@ void ObjHeader::destroyMetaObject(TypeInfo** location) {
|
||||
WeakReferenceCounterClear(meta->counter_);
|
||||
UpdateRef(&meta->counter_, nullptr);
|
||||
}
|
||||
|
||||
#ifdef KONAN_OBJC_INTEROP
|
||||
Kotlin_ObjCExport_releaseAssociatedObject(meta->associatedObject);
|
||||
#endif
|
||||
|
||||
konanFreeMemory(meta);
|
||||
}
|
||||
|
||||
@@ -920,7 +913,7 @@ void FreeContainer(ContainerHeader* container) {
|
||||
void ObjectContainer::Init(const TypeInfo* typeInfo) {
|
||||
RuntimeAssert(typeInfo->instanceSize_ >= 0, "Must be an object");
|
||||
uint32_t alloc_size =
|
||||
sizeof(ContainerHeader) + sizeof(ObjHeader) + typeInfo->instanceSize_ + kObjectReservedTailSize;
|
||||
sizeof(ContainerHeader) + sizeof(ObjHeader) + typeInfo->instanceSize_;
|
||||
header_ = AllocContainer(alloc_size);
|
||||
if (header_) {
|
||||
// One object in this container.
|
||||
@@ -936,7 +929,7 @@ void ArrayContainer::Init(const TypeInfo* typeInfo, uint32_t elements) {
|
||||
RuntimeAssert(typeInfo->instanceSize_ < 0, "Must be an array");
|
||||
uint32_t alloc_size =
|
||||
sizeof(ContainerHeader) + sizeof(ArrayHeader) -
|
||||
typeInfo->instanceSize_ * elements + kObjectReservedTailSize;
|
||||
typeInfo->instanceSize_ * elements;
|
||||
header_ = AllocContainer(alloc_size);
|
||||
RuntimeAssert(header_ != nullptr, "Cannot alloc memory");
|
||||
if (header_) {
|
||||
@@ -1019,7 +1012,7 @@ ObjHeader** ArenaContainer::getSlot() {
|
||||
|
||||
ObjHeader* ArenaContainer::PlaceObject(const TypeInfo* type_info) {
|
||||
RuntimeAssert(type_info->instanceSize_ >= 0, "must be an object");
|
||||
uint32_t size = type_info->instanceSize_ + sizeof(ObjHeader) + kObjectReservedTailSize;
|
||||
uint32_t size = type_info->instanceSize_ + sizeof(ObjHeader);
|
||||
ObjHeader* result = reinterpret_cast<ObjHeader*>(place(size));
|
||||
if (!result) {
|
||||
return nullptr;
|
||||
@@ -1032,7 +1025,7 @@ ObjHeader* ArenaContainer::PlaceObject(const TypeInfo* type_info) {
|
||||
|
||||
ArrayHeader* ArenaContainer::PlaceArray(const TypeInfo* type_info, uint32_t count) {
|
||||
RuntimeAssert(type_info->instanceSize_ < 0, "must be an array");
|
||||
container_size_t size = sizeof(ArrayHeader) - type_info->instanceSize_ * count + kObjectReservedTailSize;
|
||||
container_size_t size = sizeof(ArrayHeader) - type_info->instanceSize_ * count;
|
||||
ArrayHeader* result = reinterpret_cast<ArrayHeader*>(place(size));
|
||||
if (!result) {
|
||||
return nullptr;
|
||||
@@ -1220,16 +1213,6 @@ OBJ_GETTER(InitSharedInstance,
|
||||
#endif
|
||||
}
|
||||
|
||||
bool HasReservedObjectTail(ObjHeader* obj) {
|
||||
return kObjectReservedTailSize != 0 && !obj->permanent();
|
||||
}
|
||||
|
||||
void* GetReservedObjectTail(ObjHeader* obj) {
|
||||
return reinterpret_cast<void*>(
|
||||
reinterpret_cast<uintptr_t>(obj) + objectSize(obj) - kObjectReservedTailSize
|
||||
);
|
||||
}
|
||||
|
||||
void SetRef(ObjHeader** location, const ObjHeader* object) {
|
||||
MEMORY_LOG("SetRef *%p: %p\n", location, object)
|
||||
*const_cast<const ObjHeader**>(location) = object;
|
||||
|
||||
@@ -244,6 +244,10 @@ struct MetaObjHeader {
|
||||
const TypeInfo* typeInfo_;
|
||||
// Strong reference to counter object.
|
||||
ObjHeader* counter_;
|
||||
|
||||
#ifdef KONAN_OBJC_INTEROP
|
||||
void* associatedObject;
|
||||
#endif
|
||||
};
|
||||
|
||||
inline uint32_t ArrayDataSizeBytes(const ArrayHeader* obj) {
|
||||
|
||||
@@ -11,16 +11,12 @@
|
||||
extern "C" id objc_retain(id self);
|
||||
extern "C" void objc_release(id self);
|
||||
|
||||
inline static bool HasAssociatedObjectField(ObjHeader* obj) {
|
||||
return HasReservedObjectTail(obj);
|
||||
}
|
||||
|
||||
inline static id GetAssociatedObject(ObjHeader* obj) {
|
||||
return *reinterpret_cast<id*>(GetReservedObjectTail(obj));
|
||||
return (id)obj->meta_object()->associatedObject;
|
||||
}
|
||||
|
||||
inline static void SetAssociatedObject(ObjHeader* obj, id value) {
|
||||
*reinterpret_cast<id*>(GetReservedObjectTail(obj)) = value;
|
||||
obj->meta_object()->associatedObject = (void*)value;
|
||||
}
|
||||
|
||||
extern "C" id Kotlin_ObjCExport_refToObjC(ObjHeader* obj);
|
||||
|
||||
@@ -105,7 +105,6 @@ extern "C" id Kotlin_ObjCExport_GetAssociatedObject(ObjHeader* obj) {
|
||||
|
||||
inline static OBJ_GETTER(AllocInstanceWithAssociatedObject, const TypeInfo* typeInfo, id associatedObject) {
|
||||
ObjHeader* result = AllocInstance(typeInfo, OBJ_RESULT);
|
||||
RuntimeAssert(HasAssociatedObjectField(result), "");
|
||||
SetAssociatedObject(result, associatedObject);
|
||||
return result;
|
||||
}
|
||||
@@ -157,7 +156,6 @@ static void initializeClass(Class clazz);
|
||||
UpdateRef(&result->kotlinObj, obj);
|
||||
|
||||
if (!obj->permanent()) {
|
||||
RuntimeAssert(HasAssociatedObjectField(obj), "");
|
||||
SetAssociatedObject(obj, result);
|
||||
}
|
||||
// TODO: permanent objects should probably be supported as custom types.
|
||||
@@ -196,11 +194,9 @@ static void initializeClass(Class clazz);
|
||||
|
||||
@end;
|
||||
|
||||
extern "C" void Kotlin_ObjCExport_releaseReservedObjectTail(ObjHeader* obj) {
|
||||
RuntimeAssert(HasAssociatedObjectField(obj), "");
|
||||
id associatedObject = GetAssociatedObject(obj);
|
||||
extern "C" void Kotlin_ObjCExport_releaseAssociatedObject(void* associatedObject) {
|
||||
if (associatedObject != nullptr) {
|
||||
[associatedObject releaseAsAssociatedObject];
|
||||
[((id)associatedObject) releaseAsAssociatedObject];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -501,7 +497,7 @@ static id Kotlin_ObjCExport_refToObjC_slowpath(ObjHeader* obj);
|
||||
extern "C" id Kotlin_ObjCExport_refToObjC(ObjHeader* obj) {
|
||||
if (obj == nullptr) return nullptr;
|
||||
|
||||
if (HasAssociatedObjectField(obj)) {
|
||||
if (obj->has_meta_object()) {
|
||||
id associatedObject = GetAssociatedObject(obj);
|
||||
if (associatedObject != nullptr) {
|
||||
return objc_retainAutoreleaseReturnValue(associatedObject);
|
||||
|
||||
@@ -118,7 +118,6 @@ static inline OBJ_GETTER(invokeAndAssociate, KRef (*func)(KRef* result), id obj)
|
||||
|
||||
KRef kotlinObj = func(OBJ_RESULT);
|
||||
|
||||
RuntimeAssert(HasAssociatedObjectField(kotlinObj), "");
|
||||
SetAssociatedObject(kotlinObj, obj);
|
||||
|
||||
return kotlinObj;
|
||||
|
||||
Reference in New Issue
Block a user