Use meta object for storing associated Objective-C object

This commit is contained in:
Svyatoslav Scherbina
2018-04-03 10:03:28 +03:00
committed by SvyatoslavScherbina
parent 841bb51e65
commit 38f896649c
8 changed files with 20 additions and 53 deletions
@@ -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 {
@@ -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.
-1
View File
@@ -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
+11 -28
View File
@@ -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;
+4
View File
@@ -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) {
+2 -6
View File
@@ -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);
+3 -7
View File
@@ -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;