diff --git a/Test/AllocatePair.m b/Test/AllocatePair.m index 9a4cf47..62969f6 100644 --- a/Test/AllocatePair.m +++ b/Test/AllocatePair.m @@ -21,9 +21,17 @@ int main() b = objc_allocateClassPair(a, "B", 0); class_addMethod(object_getClass(b), @selector(load), (IMP)load, "@:"); + + class_addIvar(b, "anIvar", 4, 2, "i"); objc_registerClassPair(b); + + Ivar iv = class_getInstanceVariable(b, "anIvar"); + size_t superSize = class_getInstanceSize([Test class]); + assert(ivar_getOffset(iv) == superSize); + class_getSuperclass(b); + c = objc_allocateClassPair(b, "C", 0); objc_registerClassPair(c); d = objc_allocateClassPair(c, "D", 0); diff --git a/runtime.c b/runtime.c index 36db616..deceda6 100644 --- a/runtime.c +++ b/runtime.c @@ -138,11 +138,9 @@ BOOL class_addIvar(Class cls, const char *name, size_t size, uint8_t alignment, offset <<= alignment; } - // FIXME: This is stupid, but it will work for testing. - ivar->offset = malloc(sizeof(int)); - *ivar->offset = offset; + ivar->offset = (int*)(uintptr_t)offset; // Increase the instance size to make space for this. - cls->instance_size = *ivar->offset + size; + cls->instance_size = offset + size; return YES; } @@ -584,6 +582,13 @@ static void freeIvarLists(Class aClass) struct objc_ivar_list *ivarlist = aClass->ivars; if (NULL == ivarlist) { return; } + if (ivarlist->count > 0) + { + // For dynamically created classes, ivar offset variables are allocated + // as a contiguous range starting with the first one. + free(ivarlist->ivar_list[0].offset); + } + for (int i=0 ; icount ; i++) { Ivar ivar = &ivarlist->ivar_list[i]; @@ -755,6 +760,15 @@ PRIVATE void objc_resolve_class(Class); void objc_registerClassPair(Class cls) { + if (cls->ivars != NULL) + { + int *ptrs = calloc(cls->ivars->count, sizeof(int)); + for (int i=0 ; iivars->count ; i++) + { + ptrs[i] = (int)(intptr_t)cls->ivars->ivar_list[i].offset; + cls->ivars->ivar_list[i].offset = &ptrs[i]; + } + } LOCK_RUNTIME_FOR_SCOPE(); class_table_insert(cls); objc_resolve_class(cls);