Skip to content

Commit c0f56a7

Browse files
committed
Modify ivar flags.
Add a flag to indicate that instance variables have an extended type encoding. Remove the alignment field and replace it with 6 bits from the flags field. We only support power of two alignments, so we may as well store them in log form, which means we can save a field. Note that this doesn't actually save us any space except on 32-bit platforms, because alignment means that we end up with extra padding at the end of the struct.
1 parent ccefff2 commit c0f56a7

File tree

4 files changed

+48
-15
lines changed

4 files changed

+48
-15
lines changed

Diff for: ivar.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,14 @@ PRIVATE void objc_compute_ivar_offsets(Class class)
7878
// We only need to do the realignment for things that are
7979
// bigger than a pointer, and we don't need to do it in GC mode
8080
// where we don't add any extra padding.
81-
if (!isGCEnabled && (ivar->align > __alignof__(void*)))
81+
if (!isGCEnabled && (ivarGetAlign(ivar) > __alignof__(void*)))
8282
{
8383
long offset = ivar_start + *ivar->offset + sizeof(intptr_t);
84-
long fudge = ivar->align - (offset % ivar->align);
84+
long fudge = ivarGetAlign(ivar) - (offset % ivarGetAlign(ivar));
8585
*ivar->offset += fudge;
8686
class->instance_size += fudge;
8787
cumulative_fudge += fudge;
88-
assert((ivar_start + *ivar->offset + sizeof(intptr_t)) % ivar->align == 0);
88+
assert((ivar_start + *ivar->offset + sizeof(intptr_t)) % ivarGetAlign(ivar) == 0);
8989
}
9090
*ivar->offset += ivar_start;
9191
}

Diff for: ivar.h

+42-9
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,11 @@ struct objc_ivar
2020
* the ivars declared by this class. It is then set by the runtime to the
2121
* offset from the object pointer.
2222
*/
23-
int *offset;
24-
/**
25-
* Alignment of this ivar.
26-
*/
27-
int32_t align;
23+
int *offset;
2824
/**
2925
* Flags for this instance variable.
3026
*/
31-
int32_t flags;
27+
uint32_t flags;
3228
};
3329

3430
/**
@@ -56,15 +52,52 @@ typedef enum {
5652
} ivar_ownership;
5753

5854
/**
59-
* Mask applied to the flags field to indicate ownership.
60-
*/
61-
static const int ivar_ownership_mask = 3;
55+
* Shift for instance variable alignment. */
56+
static const int ivar_align_shift = 3;
57+
58+
typedef enum {
59+
/**
60+
* Mask applied to the flags field to indicate ownership.
61+
*/
62+
ivar_ownership_mask = (1<<0) | (1<<1),
63+
/**
64+
* Flag indicating that the ivar contains an extended type encoding.
65+
*/
66+
ivar_extended_type_encoding = (1<<2),
67+
/**
68+
* Mask for describing the alignment. We need 6 bits to represent any
69+
* power of two aligmnent from 0 to 63-bit alignment. There is probably no
70+
* point supporting more than 32-bit aligment, because various bits of
71+
* offset assume objects are less than 4GB, but there's definitely no point
72+
* in supporting 64-bit alignment because we currently don't support any
73+
* architectures where an address space could contain more than one 2^64
74+
* byte aligned value.
75+
*/
76+
ivar_align_mask = (((1<<6)-1) << ivar_align_shift)
77+
} objc_ivar_flags;
78+
79+
80+
static inline size_t ivarGetAlign(Ivar ivar)
81+
{
82+
return 1<<((ivar->flags & ivar_align_mask) >> ivar_align_shift);
83+
}
84+
85+
static inline void ivarSetAlign(Ivar ivar, size_t align)
86+
{
87+
if (align != 0)
88+
{
89+
align = sizeof(size_t) * 8 - __builtin_clz(align) - 1;
90+
}
91+
align <<= ivar_align_shift;
92+
ivar->flags = (ivar->flags & ~ivar_align_mask) | align;
93+
}
6294

6395
static inline void ivarSetOwnership(Ivar ivar, ivar_ownership o)
6496
{
6597
ivar->flags = (ivar->flags & ~ivar_ownership_mask) | o;
6698
}
6799

100+
68101
/**
69102
* Look up the ownership for a given instance variable.
70103
*/

Diff for: legacy.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,10 @@ static struct objc_ivar_list *upgradeIvarList(struct objc_class_gsv1 *cls)
9494
{
9595
n->ivar_list[i].offset = &l->ivar_list[i].offset;
9696
}
97-
n->ivar_list[i].align = ((type == NULL) || type[0] == 0) ? __alignof__(void*) : objc_alignof_type(type);
97+
ivarSetAlign(&n->ivar_list[i], ((type == NULL) || type[0] == 0) ? __alignof__(void*) : objc_alignof_type(type));
9898
if (type[0] == '\0')
9999
{
100-
n->ivar_list[i].align = size;
100+
ivarSetAlign(&n->ivar_list[i], size);
101101
}
102102
ivarSetOwnership(&n->ivar_list[i], ownershipForIvar(cls, i));
103103
}

Diff for: runtime.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ BOOL class_addIvar(Class cls, const char *name, size_t size, uint8_t alignment,
124124
Ivar ivar = ivar_at_index(cls->ivars, cls->ivars->count - 1);
125125
ivar->name = strdup(name);
126126
ivar->type = strdup(types);
127-
ivar->align = alignment;
127+
ivarSetAlign(ivar, alignment);
128128
// Round up the offset of the ivar so it is correctly aligned.
129129
long offset = cls->instance_size;
130130
if (alignment != 0)

0 commit comments

Comments
 (0)