/* realizeClass * Performs first-time initialization on class cls, * including allocating its read-write data. * Returns the real class structure for the class. * Locking: runtimeLock must be write-locked by the caller */ static Class realizeClass(Class cls){ class_rw_t *rw = cls->data(); //...省略 if (ro->instanceStart < super_ro->instanceSize) { // Superclass has changed size. This class's ivars must move. // Also slide layout bits in parallel. // This code is incapable of compacting the subclass to // compensate for a superclass that shrunk, so don't do that. class_ro_t *ro_w = make_ro_writeable(rw); ro = rw->ro; moveIvars(ro_w, super_ro->instanceSize, mergeLayouts ? &ivarBitmap : nil, mergeLayouts ? &weakBitmap : nil); gdb_objc_class_changed(cls, OBJC_CLASS_IVARS_CHANGED, ro->name); layoutsChanged = YES; } // ...省略 }
/*********************************************************************** * moveIvars * Slides a class's ivars to accommodate the given superclass size. * Also slides ivar and weak GC layouts if provided. * Ivars are NOT compacted to compensate for a superclass that shrunk. * Locking: runtimeLock must be held by the caller. **********************************************************************/ staticvoidmoveIvars(class_ro_t *ro, uint32_t superSize, layout_bitmap *ivarBitmap, layout_bitmap *weakBitmap) { rwlock_assert_writing(&runtimeLock);
if (ro->ivars) { // Find maximum alignment in this class's ivars uint32_t maxAlignment = 1; for (i = 0; i < ro->ivars->count; i++) { ivar_t *ivar = ivar_list_nth(ro->ivars, i); if (!ivar->offset) continue; // anonymous bitfield
// Compute a slide value that preserves that alignment uint32_t alignMask = maxAlignment - 1; if (diff & alignMask) diff = (diff + alignMask) & ~alignMask;
// Slide all of this class's ivars en masse for (i = 0; i < ro->ivars->count; i++) { ivar_t *ivar = ivar_list_nth(ro->ivars, i); if (!ivar->offset) continue; // anonymous bitfield
if (!ro->ivars) { // No ivars slid, but superclass changed size. // Expand bitmap in preparation for layout_bitmap_splat(). if (ivarBitmap) layout_bitmap_grow(ivarBitmap, ro->instanceSize >> WORD_SHIFT); if (weakBitmap) layout_bitmap_grow(weakBitmap, ro->instanceSize >> WORD_SHIFT); } }
his function may only be called after objc_allocateClassPair and before objc_registerClassPair. Adding an instance variable to an existing class is not supported. The class must not be a metaclass. Adding an instance variable to a metaclass is not supported.
@interfaceSon : Father @property (nonatomic, copy) NSArray *toys; @end
当Father初始化之后,instanceStart,instanceSize,offset已经确定。 为 Father 添加新的成员变量 sex,则使用 Son 的实例对象 son 会出错误,因为 son.instanceStart < Father.instanceSize,即 father 成员变量的 sex 的内存区域会跟 son 的一部分重合