diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt index f8b66ac8bca..9f6edf7832e 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt @@ -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 { diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt index 22bf044d22d..079aaed92b8 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt @@ -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. diff --git a/runtime/src/main/cpp/Common.h b/runtime/src/main/cpp/Common.h index a2e29eaa257..15d954f2aea 100644 --- a/runtime/src/main/cpp/Common.h +++ b/runtime/src/main/cpp/Common.h @@ -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 diff --git a/runtime/src/main/cpp/Memory.cpp b/runtime/src/main/cpp/Memory.cpp index 01bc0b3f2c7..4fe3209fdb3 100644 --- a/runtime/src/main/cpp/Memory.cpp +++ b/runtime/src/main/cpp/Memory.cpp @@ -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(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(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(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( - reinterpret_cast(obj) + objectSize(obj) - kObjectReservedTailSize - ); -} - void SetRef(ObjHeader** location, const ObjHeader* object) { MEMORY_LOG("SetRef *%p: %p\n", location, object) *const_cast(location) = object; diff --git a/runtime/src/main/cpp/Memory.h b/runtime/src/main/cpp/Memory.h index 390e8185edc..aa4dcc73dd2 100644 --- a/runtime/src/main/cpp/Memory.h +++ b/runtime/src/main/cpp/Memory.h @@ -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) { diff --git a/runtime/src/main/cpp/ObjCExport.h b/runtime/src/main/cpp/ObjCExport.h index 9adc6bd0aeb..b392fda7d0f 100644 --- a/runtime/src/main/cpp/ObjCExport.h +++ b/runtime/src/main/cpp/ObjCExport.h @@ -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(GetReservedObjectTail(obj)); + return (id)obj->meta_object()->associatedObject; } inline static void SetAssociatedObject(ObjHeader* obj, id value) { - *reinterpret_cast(GetReservedObjectTail(obj)) = value; + obj->meta_object()->associatedObject = (void*)value; } extern "C" id Kotlin_ObjCExport_refToObjC(ObjHeader* obj); diff --git a/runtime/src/main/cpp/ObjCExport.mm b/runtime/src/main/cpp/ObjCExport.mm index 5ce0e843dff..6f14fa701cd 100644 --- a/runtime/src/main/cpp/ObjCExport.mm +++ b/runtime/src/main/cpp/ObjCExport.mm @@ -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); diff --git a/runtime/src/main/cpp/ObjCExportCollections.mm b/runtime/src/main/cpp/ObjCExportCollections.mm index 344a1513947..a1a6024bbef 100644 --- a/runtime/src/main/cpp/ObjCExportCollections.mm +++ b/runtime/src/main/cpp/ObjCExportCollections.mm @@ -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;