* (5) is not yet eligible for +load.
*
* Image mapping is NOT CURRENTLY THREAD-SAFE with respect to just about
- * * * anything. Image mapping IS RE-ENTRANT in several places: superclass
+ * anything. Image mapping IS RE-ENTRANT in several places: superclass
* lookup may cause ZeroLink to load another image, and +load calls may
* cause dyld to load another image.
*
* Read all classes in all new images.
* Add them all to unconnected_class_hash.
* Note any +load implementations before categories are attached.
- * Fix up any pended classrefs referring to them.
* Attach any pending categories.
* Read all categories in all new images.
* Attach categories whose parent class exists (connected or not),
* If the superclass is connected:
* connect the class
* mark the class eligible for +load, if implemented
+ * fix up any pended classrefs referring to the class
* connect any pended subclasses of the class
* Resolve selector refs and class refs in all new images.
* Class refs whose classes still do not exist are pended.
* are attached. Otherwise, if a category implements +load and its class
* has no class methods, the class's +load scan would find the category's
* +load method, which would then be called twice.
+ *
+ * Correctness: pended class refs are not fixed up until the class is
+ * connected. Classes with missing weak superclasses remain unconnected.
+ * Class refs to classes with missing weak superclasses must be NULL.
+ * Therefore class refs to unconnected classes must remain un-fixed.
*
**********************************************************************/
mutex_unlock(&classLock);
+ // Fix up pended class refs to this class, if any
+ resolve_references_to_class(cls);
+
// Connect newly-connectable subclasses
resolve_subclasses_of_class(cls);
mutex_unlock(&classLock);
if (!rejected) {
- // Fix up pended class refs to this class, if any
- resolve_references_to_class(newCls);
-
// Attach pended categories for this class, if any
resolve_categories_for_class(newCls);
}
struct old_class *cls;
// Get pointer to class of this name
- // YES unconnected, YES class loader
- cls = _class_asOld((Class)look_up_class(name, YES, YES));
+ // NO unconnected, YES class loader
+ // (real class with weak-missing superclass is unconnected now)
+ cls = _class_asOld((Class)look_up_class(name, NO, YES));
if (cls) {
// Referenced class exists. Fix up the reference.
*ref = isMeta ? cls->isa : cls;
} else {
- // Referenced class does not exist yet. Insert a placeholder
- // class and fix up the reference later.
+ // Referenced class does not exist yet. Insert NULL for now
+ // (weak-linking) and fix up the reference if the class arrives later.
pendClassReference (ref, name, isMeta);
- *ref = (struct old_class *)_class_getNonexistentObjectClass();
+ *ref = NULL;
}
}
if (!pendingClassRefsMap) return;
// Search the pending class ref table for class refs in this range.
- // The class refs may have already been stomped with nonexistentClass,
+ // The class refs may have already been stomped with NULL,
// so there's no way to recover the original class name.
{
if ((uintptr_t)(refs[i]) >= start && (uintptr_t)(refs[i]) < end) {
pendClassReference(&refs[i], refs[i]->name,
(refs[i]->info & CLS_META) ? YES : NO);
- refs[i] = (struct old_class *)_class_getNonexistentObjectClass();
+ refs[i] = NULL;
}
}
}