Checkpoint more work on new ABI.

We're now using a new class and category structure and auto-upgrading the old ones.  Other changes:

- The Ivar structure now points to the ivar offset variable, so we can more easily find it.
- Categories can now add properties.
main
David Chisnall 8 years ago
parent 09dda1837f
commit f91fb2e745

@ -42,6 +42,7 @@ set(libobjc_C_SRCS
hooks.c hooks.c
ivar.c ivar.c
legacy_malloc.c legacy_malloc.c
legacy.c
loader.c loader.c
mutation.m mutation.m
protocol.c protocol.c

@ -1,14 +1,9 @@
#pragma once
/** /**
* The structure used to represent a category. * The structure used to represent a category.
* *
* This provides a set of new definitions that are used to replace those * This provides a set of new definitions that are used to replace those
* contained within a class. * contained within a class.
*
* Note: Objective-C 2 allows properties to be added to classes. The current
* ABI does not provide a field for adding properties in categories. This is
* likely to be added with ABI version 10. Until then, the methods created by
* a declared property will work, but introspection on the property will not.
*/ */
struct objc_category struct objc_category
{ {
@ -34,8 +29,34 @@ struct objc_category
struct objc_protocol_list *protocols; struct objc_protocol_list *protocols;
/** /**
* The list of properties added by this category * The list of properties added by this category
*
* Only present in V2 ABI!
*/ */
struct objc_property_list *properties; struct objc_property_list *properties;
/**
* Class properties.
*/
struct objc_property_list *class_properties;
};
struct objc_category_legacy
{
/**
* The name of this category.
*/
const char *name;
/**
* The name of the class to which this category should be applied.
*/
const char *class_name;
/**
* The list of instance methods to add to the class.
*/
struct objc_method_list *instance_methods;
/**
* The list of class methods to add to the class.
*/
struct objc_method_list *class_methods;
/**
* The list of protocols adopted by this category.
*/
struct objc_protocol_list *protocols;
}; };

@ -3,6 +3,7 @@
#include "visibility.h" #include "visibility.h"
#include "loader.h" #include "loader.h"
#include "dtable.h" #include "dtable.h"
#include "properties.h"
#define BUFFER_TYPE struct objc_category * #define BUFFER_TYPE struct objc_category *
#include "buffer.h" #include "buffer.h"
@ -39,6 +40,16 @@ static void load_category(struct objc_category *cat, struct objc_class *class)
cat->protocols->next = class->protocols; cat->protocols->next = class->protocols;
class->protocols = cat->protocols; class->protocols = cat->protocols;
} }
if (cat->properties)
{
cat->properties->next = class->properties;
class->properties = cat->properties;
}
if (cat->class_properties)
{
cat->class_properties->next = class->isa->properties;
class->isa->properties = cat->class_properties;
}
} }
static BOOL try_load_category(struct objc_category *cat) static BOOL try_load_category(struct objc_category *cat)

@ -1,6 +1,7 @@
#ifndef __OBJC_CLASS_H_INCLUDED #ifndef __OBJC_CLASS_H_INCLUDED
#define __OBJC_CLASS_H_INCLUDED #define __OBJC_CLASS_H_INCLUDED
#include "visibility.h" #include "visibility.h"
#include <stdint.h>
/** /**
* Overflow bitfield. Used for bitfields that are more than 63 bits. * Overflow bitfield. Used for bitfields that are more than 63 bits.
@ -118,6 +119,101 @@ struct objc_class
* ABI by using the CLS_ISNEW_ABI() macro. * ABI by using the CLS_ISNEW_ABI() macro.
*/ */
/**
* The version of the ABI used for this class. Zero indicates the ABI first
* implemented by clang 1.0. One indicates the presence of bitmaps
* indicating the offsets of strong, weak, and unretained ivars. Two
* indicates that the new ivar structure is used.
*/
long abi_version;
/**
* List of declared properties on this class (NULL if none).
*/
struct objc_property_list *properties;
};
struct legacy_gnustep_objc_class
{
/**
* Pointer to the metaclass for this class. The metaclass defines the
* methods use when a message is sent to the class, rather than an
* instance.
*/
struct objc_class *isa;
/**
* Pointer to the superclass. The compiler will set this to the name of
* the superclass, the runtime will initialize it to point to the real
* class.
*/
struct objc_class *super_class;
/**
* The name of this class. Set to the same value for both the class and
* its associated metaclass.
*/
const char *name;
/**
* The version of this class. This is not used by the language, but may be
* set explicitly at class load time.
*/
long version;
/**
* A bitfield containing various flags. See the objc_class_flags
* enumerated type for possible values.
*/
unsigned long info;
/**
* The size of this class. For classes using the non-fragile ABI, the
* compiler will set this to a negative value The absolute value will be
* the size of the instance variables defined on just this class. When
* using the fragile ABI, the instance size is the size of instances of
* this class, including any instance variables defined on superclasses.
*
* In both cases, this will be set to the size of an instance of the class
* after the class is registered with the runtime.
*/
long instance_size;
/**
* Metadata describing the instance variables in this class.
*/
struct objc_ivar_list_legacy *ivars;
/**
* Metadata for for defining the mappings from selectors to IMPs. Linked
* list of method list structures, one per class and one per category.
*/
struct objc_method_list *methods;
/**
* The dispatch table for this class. Intialized and maintained by the
* runtime.
*/
void *dtable;
/**
* A pointer to the first subclass for this class. Filled in by the
* runtime.
*/
struct objc_class *subclass_list;
/**
* A pointer to the next sibling class to this. You may find all
* subclasses of a given class by following the subclass_list pointer and
* then subsequently following the sibling_class pointers in the
* subclasses.
*/
struct objc_class *sibling_class;
/**
* Metadata describing the protocols adopted by this class. Not used by
* the runtime.
*/
struct objc_protocol_list *protocols;
/**
* Linked list of extra data attached to this class.
*/
struct reference_list *extra_data;
/**
* New ABI. The following fields are only available with classes compiled to
* support the new ABI. You may test whether any given class supports this
* ABI by using the CLS_ISNEW_ABI() macro.
*/
/** /**
* The version of the ABI used for this class. Zero indicates the ABI first * The version of the ABI used for this class. Zero indicates the ABI first
* implemented by clang 1.0. One indicates the presence of bitmaps * implemented by clang 1.0. One indicates the presence of bitmaps
@ -170,12 +266,12 @@ struct objc_class
}; };
/** /**
* Structure representing the old ABI class structure. This is only ever * Structure representing the GCC ABI class structure. This is only ever
* required so that we can take its size - struct objc_class begins with the * required so that we can take its size - struct objc_class begins with the
* same fields, and you can test the new abi flag to tell whether it is safe to * same fields, and you can test the new abi flag to tell whether it is safe to
* access the subsequent fields. * access the subsequent fields.
*/ */
struct legacy_abi_objc_class struct legacy_gcc_objc_class
{ {
struct objc_class *isa; struct objc_class *isa;
struct objc_class *super_class; struct objc_class *super_class;
@ -183,7 +279,7 @@ struct legacy_abi_objc_class
long version; long version;
unsigned long info; unsigned long info;
long instance_size; long instance_size;
struct objc_ivar_list *ivars; struct objc_ivar_list_legacy *ivars;
struct objc_method_list *methods; struct objc_method_list *methods;
void *dtable; void *dtable;
struct objc_class *subclass_list; struct objc_class *subclass_list;
@ -266,6 +362,12 @@ static inline BOOL objc_test_class_flag(struct objc_class *aClass,
{ {
return (aClass->info & (unsigned long)flag) == (unsigned long)flag; return (aClass->info & (unsigned long)flag) == (unsigned long)flag;
} }
static inline BOOL objc_test_class_flag_legacy(struct legacy_gnustep_objc_class *aClass,
enum objc_class_flags flag)
{
return (aClass->info & (unsigned long)flag) == (unsigned long)flag;
}
/** /**
* Checks the version of a class. Return values are: * Checks the version of a class. Return values are:
* 0. Legacy GCC ABI compatible class. * 0. Legacy GCC ABI compatible class.
@ -282,6 +384,15 @@ static inline int objc_get_class_version(struct objc_class *aClass)
return aClass->abi_version + 1; return aClass->abi_version + 1;
} }
static inline int objc_get_class_version_legacy(struct legacy_gnustep_objc_class *aClass)
{
if (!objc_test_class_flag_legacy(aClass, objc_class_flag_new_abi))
{
return 0;
}
return aClass->abi_version + 1;
}
/** /**
* Adds a class to the class table. * Adds a class to the class table.
*/ */

@ -12,7 +12,6 @@
#include <stdlib.h> #include <stdlib.h>
#include <assert.h> #include <assert.h>
void objc_register_selectors_from_class(Class class);
void objc_init_protocols(struct objc_protocol_list *protos); void objc_init_protocols(struct objc_protocol_list *protos);
void objc_compute_ivar_offsets(Class class); void objc_compute_ivar_offsets(Class class);
@ -243,6 +242,12 @@ PRIVATE BOOL objc_resolve_class(Class cls)
// Fix up the ivar offsets // Fix up the ivar offsets
objc_compute_ivar_offsets(cls); objc_compute_ivar_offsets(cls);
struct legacy_gnustep_objc_class *oldCls = objc_legacy_class_for_class(cls);
if (oldCls)
{
oldCls->super_class = cls->super_class;
oldCls->isa->super_class = cls->isa->super_class;
}
// Send the +load message, if required // Send the +load message, if required
if (!objc_test_class_flag(cls, objc_class_flag_user_created)) if (!objc_test_class_flag(cls, objc_class_flag_user_created))
{ {
@ -361,10 +366,6 @@ static void reload_class(struct objc_class *class, struct objc_class *old)
// this class will now return this class. // this class will now return this class.
class_table_internal_table_set(class_table, (void*)class->name, class); class_table_internal_table_set(class_table, (void*)class->name, class);
// Register all of the selectors used by this class and its metaclass
objc_register_selectors_from_class(class);
objc_register_selectors_from_class(class->isa);
// Set the uninstalled dtable. The compiler could do this as well. // Set the uninstalled dtable. The compiler could do this as well.
class->dtable = uninstalled_dtable; class->dtable = uninstalled_dtable;
class->isa->dtable = uninstalled_dtable; class->isa->dtable = uninstalled_dtable;
@ -415,10 +416,6 @@ PRIVATE void objc_load_class(struct objc_class *class)
// Insert the class into the class table // Insert the class into the class table
class_table_insert(class); class_table_insert(class);
// Register all of the selectors used by this class and its metaclass
objc_register_selectors_from_class(class);
objc_register_selectors_from_class(class->isa);
// Set the uninstalled dtable. The compiler could do this as well. // Set the uninstalled dtable. The compiler could do this as well.
class->dtable = uninstalled_dtable; class->dtable = uninstalled_dtable;
class->isa->dtable = uninstalled_dtable; class->isa->dtable = uninstalled_dtable;

@ -11,7 +11,6 @@
ptrdiff_t objc_alignof_type(const char *); ptrdiff_t objc_alignof_type(const char *);
ptrdiff_t objc_sizeof_type(const char *); ptrdiff_t objc_sizeof_type(const char *);
static struct objc_ivar_list *upgradeIvarList(Class cls, struct objc_ivar_list_legacy *l);
PRIVATE void objc_compute_ivar_offsets(Class class) PRIVATE void objc_compute_ivar_offsets(Class class)
{ {
@ -25,13 +24,6 @@ PRIVATE void objc_compute_ivar_offsets(Class class)
} }
return; return;
} }
// If this is an old ABI class, then replace the ivar list with the new
// version
if (objc_get_class_version(class) < 3)
{
legacy = (struct objc_ivar_list_legacy *)class->ivars;
class->ivars = upgradeIvarList(class, legacy);
}
if (class->ivars->size != sizeof(struct objc_ivar)) if (class->ivars->size != sizeof(struct objc_ivar))
{ {
fprintf(stderr, "Downgrading ivar struct not yet implemented"); fprintf(stderr, "Downgrading ivar struct not yet implemented");
@ -79,49 +71,47 @@ PRIVATE void objc_compute_ivar_offsets(Class class)
// the time, but if we have an instance variable that is a vector type // the time, but if we have an instance variable that is a vector type
// then we will need to ensure that we are properly aligned again. // then we will need to ensure that we are properly aligned again.
long ivar_size = (i+1 == class->ivars->count) long ivar_size = (i+1 == class->ivars->count)
? (class_size - ivar->offset) ? (class_size - *ivar->offset)
: class->ivars->ivar_list[i+1].offset - ivar->offset ; : *class->ivars->ivar_list[i+1].offset - *ivar->offset ;
// FIXME: use alignment // FIXME: use alignment
ivar->offset += cumulative_fudge; *ivar->offset += cumulative_fudge;
// We only need to do the realignment for things that are // We only need to do the realignment for things that are
// bigger than a pointer, and we don't need to do it in GC mode // bigger than a pointer, and we don't need to do it in GC mode
// where we don't add any extra padding. // where we don't add any extra padding.
if (!isGCEnabled && (ivar_size > sizeof(void*))) if (!isGCEnabled && (ivar_size > sizeof(void*)))
{ {
long offset = ivar_start + ivar->offset + sizeof(intptr_t); long offset = ivar_start + *ivar->offset + sizeof(intptr_t);
// For now, assume that nothing needs to be more than 16-byte aligned. // For now, assume that nothing needs to be more than 16-byte aligned.
// This is not correct for AVX vectors, but we probably // This is not correct for AVX vectors, but we probably
// can't do anything about that for now (as malloc is only // can't do anything about that for now (as malloc is only
// giving us 16-byte aligned memory) // giving us 16-byte aligned memory)
long fudge = 16 - (offset % 16); long fudge = 16 - (offset % 16);
ivar->offset += fudge; *ivar->offset += fudge;
class->instance_size += fudge; class->instance_size += fudge;
cumulative_fudge += fudge; cumulative_fudge += fudge;
assert((ivar_start + ivar->offset + sizeof(intptr_t)) % 16 == 0); assert((ivar_start + *ivar->offset + sizeof(intptr_t)) % 16 == 0);
}
ivar->offset += ivar_start;
/* If we're using the new ABI then we also set up the faster ivar
* offset variables.
*/
if (objc_test_class_flag(class, objc_class_flag_new_abi))
{
*(class->ivar_offsets[i]) = ivar->offset;
} }
// If we have a legacy ivar list, update the offset in it too - *ivar->offset += ivar_start;
// code from older compilers may access this directly! }
if (legacy != NULL) // If we have a legacy ivar list, update the offset in it too -
// code from older compilers may access this directly!
struct legacy_gnustep_objc_class* legacy = objc_legacy_class_for_class(class);
if (legacy)
{
for (i = 0 ; i < class->ivars->count ; i++)
{ {
legacy->ivar_list[i].offset = ivar->offset; legacy->ivars->ivar_list[i].offset = *class->ivars->ivar_list[i].offset;
} }
} }
} }
} }
else //else
if (0)
{ {
if (NULL == class->ivars) { return; } if (NULL == class->ivars) { return; }
Class super = class_getSuperclass(class); Class super = class_getSuperclass(class);
int start = class->ivars->ivar_list[0].offset; int start = *class->ivars->ivar_list[0].offset;
/* Quick and dirty test. If the first ivar comes straight after the last /* Quick and dirty test. If the first ivar comes straight after the last
* class, then it's fine. */ * class, then it's fine. */
if (Nil == super || start == super->instance_size) {return; } if (Nil == super || start == super->instance_size) {return; }
@ -136,7 +126,7 @@ PRIVATE void objc_compute_ivar_offsets(Class class)
// Find the end of the last ivar - instance_size contains some padding // Find the end of the last ivar - instance_size contains some padding
// for alignment. // for alignment.
int real_end = ivar->offset + objc_sizeof_type(ivar->type); int real_end = *ivar->offset + objc_sizeof_type(ivar->type);
// Keep going if the new class starts at the end of the superclass // Keep going if the new class starts at the end of the superclass
if (start == real_end) if (start == real_end)
{ {
@ -160,7 +150,7 @@ PRIVATE void objc_compute_ivar_offsets(Class class)
class->ivars->ivar_list[0].name, start); class->ivars->ivar_list[0].name, start);
fprintf(stderr, fprintf(stderr,
"Last instance variable in superclass, %s, ends at offset %d. ", "Last instance variable in superclass, %s, ends at offset %d. ",
ivar->name, ivar->offset + ivar->name, *ivar->offset +
(int)objc_sizeof_type(ivar->type)); (int)objc_sizeof_type(ivar->type));
fprintf(stderr, "This probably means that you are subclassing a" fprintf(stderr, "This probably means that you are subclassing a"
"class from a library, which has changed in a binary-incompatible" "class from a library, which has changed in a binary-incompatible"
@ -170,44 +160,6 @@ PRIVATE void objc_compute_ivar_offsets(Class class)
} }
ivar_ownership ownershipForIvar(Class cls, int idx)
{
if (objc_get_class_version(cls) < 2)
{
return ownership_unsafe;
}
if (objc_bitfield_test(cls->strong_pointers, idx))
{
return ownership_strong;
}
if (objc_bitfield_test(cls->weak_pointers, idx))
{
return ownership_weak;
}
return ownership_unsafe;
}
static struct objc_ivar_list *upgradeIvarList(Class cls, struct objc_ivar_list_legacy *l)
{
if (l == NULL)
{
return NULL;
}
struct objc_ivar_list *n = calloc(1, sizeof(struct objc_ivar_list) +
l->count*sizeof(struct objc_ivar));
n->size = sizeof(struct objc_ivar);
n->count = l->count;
for (int i=0 ; i<l->count ; i++)
{
n->ivar_list[i].name = l->ivar_list[i].name;
n->ivar_list[i].type = l->ivar_list[i].type;
n->ivar_list[i].offset = l->ivar_list[i].offset;
const char *type = l->ivar_list[i].type;
n->ivar_list[i].align = ((type == NULL) || type[0] == 0) ? __alignof__(void*) : objc_alignof_type(type);
ivarSetOwnership(&n->ivar_list[i], ownershipForIvar(cls, i));
}
return n;
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Public API functions // Public API functions

@ -19,15 +19,15 @@ struct objc_ivar
* the ivars declared by this class. It is then set by the runtime to the * the ivars declared by this class. It is then set by the runtime to the
* offset from the object pointer. * offset from the object pointer.
*/ */
int offset; int *offset;
/** /**
* Alignment of this ivar. * Alignment of this ivar.
*/ */
int align; int32_t align;
/** /**
* Flags for this instance variable. * Flags for this instance variable.
*/ */
long flags; int32_t flags;
}; };
/** /**

@ -0,0 +1,93 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "objc/runtime.h"
#include "objc/encoding.h"
#include "ivar.h"
#include "class.h"
#include "loader.h"
static ivar_ownership ownershipForIvar(struct legacy_gnustep_objc_class *cls, int idx)
{
if (objc_get_class_version_legacy(cls) < 2)
{
return ownership_unsafe;
}
if (objc_bitfield_test(cls->strong_pointers, idx))
{
return ownership_strong;
}
if (objc_bitfield_test(cls->weak_pointers, idx))
{
return ownership_weak;
}
return ownership_unsafe;
}
static struct objc_ivar_list *upgradeIvarList(struct legacy_gnustep_objc_class *cls)
{
struct objc_ivar_list_legacy *l = cls->ivars;
if (l == NULL)
{
return NULL;
}
struct objc_ivar_list *n = calloc(1, sizeof(struct objc_ivar_list) +
l->count*sizeof(struct objc_ivar));
n->size = sizeof(struct objc_ivar);
n->count = l->count;
for (int i=0 ; i<l->count ; i++)
{
n->ivar_list[i].name = l->ivar_list[i].name;
n->ivar_list[i].type = l->ivar_list[i].type;
if (objc_test_class_flag_legacy(cls, objc_class_flag_new_abi))
{
n->ivar_list[i].offset = cls->ivar_offsets[i];
}
else
{
n->ivar_list[i].offset = &l->ivar_list[i].offset;
}
const char *type = l->ivar_list[i].type;
n->ivar_list[i].align = ((type == NULL) || type[0] == 0) ? __alignof__(void*) : objc_alignof_type(type);
ivarSetOwnership(&n->ivar_list[i], ownershipForIvar(cls, i));
}
return n;
}
static int legacy_key;
PRIVATE struct legacy_gnustep_objc_class* objc_legacy_class_for_class(Class cls)
{
return (struct legacy_gnustep_objc_class*)objc_getAssociatedObject((id)cls, &legacy_key);
}
PRIVATE Class objc_upgrade_class(struct legacy_gnustep_objc_class *oldClass)
{
Class cls = calloc(sizeof(struct objc_class), 1);
cls->isa = oldClass->isa;
cls->super_class = (struct objc_class*)oldClass->super_class;
cls->name = oldClass->name;
cls->version = oldClass->version;
cls->info = oldClass->info;
cls->instance_size = oldClass->instance_size;
cls->ivars = upgradeIvarList(oldClass);
cls->methods = oldClass->methods;
cls->protocols = oldClass->protocols;
cls->abi_version = oldClass->abi_version;
cls->properties = oldClass->properties;
objc_register_selectors_from_class(cls);
if (!objc_test_class_flag(cls, objc_class_flag_meta))
{
cls->isa = objc_upgrade_class((struct legacy_gnustep_objc_class*)cls->isa);
objc_setAssociatedObject((id)cls, &legacy_key, (id)oldClass, OBJC_ASSOCIATION_ASSIGN);
}
return cls;
}
PRIVATE struct objc_category *objc_upgrade_category(struct objc_category_legacy *old)
{
struct objc_category *cat = calloc(1, sizeof(struct objc_category));
memcpy(cat, old, sizeof(struct objc_category_legacy));
return cat;
}

@ -0,0 +1,11 @@
#pragma once
#include "visibility.h"
#include "ivar.h"
#include "class.h"
#include "category.h"
PRIVATE Class objc_upgrade_class(struct legacy_gnustep_objc_class *oldClass);
PRIVATE struct objc_category *objc_upgrade_category(struct objc_category_legacy *);
PRIVATE struct legacy_gnustep_objc_class* objc_legacy_class_for_class(Class);

@ -6,6 +6,7 @@
#include "lock.h" #include "lock.h"
#include "loader.h" #include "loader.h"
#include "visibility.h" #include "visibility.h"
#include "legacy.h"
#ifdef ENABLE_GC #ifdef ENABLE_GC
#include <gc/gc.h> #include <gc/gc.h>
#endif #endif
@ -97,8 +98,8 @@ struct objc_init
SEL sel_end; SEL sel_end;
Class *cls_begin; Class *cls_begin;
Class *cls_end; Class *cls_end;
char **cls_ref_begin; Class *cls_ref_begin;
char **cls_ref_end; Class *cls_ref_end;
struct objc_category *cat_begin; struct objc_category *cat_begin;
struct objc_category *cat_end; struct objc_category *cat_end;
struct objc_protocol2 *proto_begin; struct objc_protocol2 *proto_begin;
@ -153,16 +154,14 @@ void __objc_load(struct objc_init *init)
} }
objc_load_class(*cls); objc_load_class(*cls);
} }
for (char **cls = init->cls_ref_begin ; cls < init->cls_ref_end ; cls++) #if 0
// We currently don't do anything with these pointers. They exist to
// provide a level of indirection that will permit us to completely change
// the `objc_class` struct without breaking the ABI (again)
for (Class *cls = init->cls_ref_begin ; cls < init->cls_ref_end ; cls++)
{ {
id *out = (id*)cls;
if (*out == nil)
{
continue;
}
*out = objc_getClass(*cls);
assert(*out);
} }
#endif
for (struct objc_category *cat = init->cat_begin ; cat < init->cat_end ; for (struct objc_category *cat = init->cat_begin ; cat < init->cat_end ;
cat++) cat++)
{ {
@ -216,13 +215,13 @@ void __objc_exec_class(struct objc_module_abi_8 *module)
// Load the classes from this module // Load the classes from this module
for (unsigned short i=0 ; i<symbols->class_count ; i++) for (unsigned short i=0 ; i<symbols->class_count ; i++)
{ {
objc_load_class(symbols->definitions[defs++]); objc_load_class(objc_upgrade_class(symbols->definitions[defs++]));
} }
unsigned int category_start = defs; unsigned int category_start = defs;
// Load the categories from this module // Load the categories from this module
for (unsigned short i=0 ; i<symbols->category_count; i++) for (unsigned short i=0 ; i<symbols->category_count; i++)
{ {
objc_try_load_category(symbols->definitions[defs++]); objc_try_load_category(objc_upgrade_category(symbols->definitions[defs++]));
} }
// Load the static instances // Load the static instances
struct objc_static_instance_list **statics = (void*)symbols->definitions[defs]; struct objc_static_instance_list **statics = (void*)symbols->definitions[defs];

@ -162,9 +162,11 @@ BOOL class_addIvar(Class cls, const char *name, size_t size, uint8_t alignment,
offset <<= alignment; offset <<= alignment;
} }
ivar->offset = offset; // FIXME: This is stupid, but it will work for testing.
ivar->offset = malloc(sizeof(int));
*ivar->offset = offset;
// Increase the instance size to make space for this. // Increase the instance size to make space for this.
cls->instance_size = ivar->offset + size; cls->instance_size = *ivar->offset + size;
return YES; return YES;
} }
@ -353,6 +355,7 @@ id class_createInstance(Class cls, size_t extraBytes)
} }
if (Nil == cls) { return nil; } if (Nil == cls) { return nil; }
assert(cls->instance_size >= sizeof(Class));
id obj = gc->allocate_class(cls, extraBytes); id obj = gc->allocate_class(cls, extraBytes);
obj->isa = cls; obj->isa = cls;
checkARCAccessorsSlow(cls); checkARCAccessorsSlow(cls);
@ -542,7 +545,7 @@ const char * ivar_getName(Ivar ivar)
ptrdiff_t ivar_getOffset(Ivar ivar) ptrdiff_t ivar_getOffset(Ivar ivar)
{ {
CHECK_ARG(ivar); CHECK_ARG(ivar);
return ivar->offset; return *ivar->offset;
} }
const char * ivar_getTypeEncoding(Ivar ivar) const char * ivar_getTypeEncoding(Ivar ivar)
@ -752,14 +755,7 @@ void *object_getIndexedIvars(id obj)
if ((0 == size) && class_isMetaClass(classForObject(obj))) if ((0 == size) && class_isMetaClass(classForObject(obj)))
{ {
Class cls = (Class)obj; Class cls = (Class)obj;
if (objc_test_class_flag(cls, objc_class_flag_new_abi)) size = sizeof(struct objc_class);
{
size = sizeof(struct objc_class);
}
else
{
size = sizeof(struct legacy_abi_objc_class);
}
} }
return ((char*)obj) + size; return ((char*)obj) + size;
} }

Loading…
Cancel
Save