Fix ivar offset calculation with alignment.

When upgrading legacy ivars, pick a sensible guess.
When calculating ivar offsets, use the supplied alignment.
main
David Chisnall 8 years ago
parent f91fb2e745
commit 5b0f05e6e0

@ -5,9 +5,9 @@
#include "objc/runtime.h" #include "objc/runtime.h"
#include "objc/objc-arc.h" #include "objc/objc-arc.h"
#include "class.h" #include "class.h"
#include "ivar.h"
#include "visibility.h" #include "visibility.h"
#include "gc_ops.h" #include "gc_ops.h"
#include "legacy.h"
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 *);
@ -78,18 +78,14 @@ PRIVATE void objc_compute_ivar_offsets(Class class)
// 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->align > __alignof__(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. long fudge = ivar->align - (offset % ivar->align);
// This is not correct for AVX vectors, but we probably
// can't do anything about that for now (as malloc is only
// giving us 16-byte aligned memory)
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)) % ivar->align == 0);
} }
*ivar->offset += ivar_start; *ivar->offset += ivar_start;
} }

@ -38,8 +38,15 @@ static struct objc_ivar_list *upgradeIvarList(struct legacy_gnustep_objc_class *
n->count = l->count; n->count = l->count;
for (int i=0 ; i<l->count ; i++) for (int i=0 ; i<l->count ; i++)
{ {
int nextOffset = (i+1 < l->count) ? l->ivar_list[i+1].offset : cls->instance_size;
if (nextOffset < 0)
{
nextOffset = -nextOffset;
}
const char *type = l->ivar_list[i].type;
int size = nextOffset - l->ivar_list[i].offset;
n->ivar_list[i].name = l->ivar_list[i].name; n->ivar_list[i].name = l->ivar_list[i].name;
n->ivar_list[i].type = l->ivar_list[i].type; n->ivar_list[i].type = type;
if (objc_test_class_flag_legacy(cls, objc_class_flag_new_abi)) if (objc_test_class_flag_legacy(cls, objc_class_flag_new_abi))
{ {
n->ivar_list[i].offset = cls->ivar_offsets[i]; n->ivar_list[i].offset = cls->ivar_offsets[i];
@ -48,8 +55,11 @@ static struct objc_ivar_list *upgradeIvarList(struct legacy_gnustep_objc_class *
{ {
n->ivar_list[i].offset = &l->ivar_list[i].offset; 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); n->ivar_list[i].align = ((type == NULL) || type[0] == 0) ? __alignof__(void*) : objc_alignof_type(type);
if (type[0] == '\0')
{
n->ivar_list[i].align = size;
}
ivarSetOwnership(&n->ivar_list[i], ownershipForIvar(cls, i)); ivarSetOwnership(&n->ivar_list[i], ownershipForIvar(cls, i));
} }
return n; return n;

Loading…
Cancel
Save