void objc_register_all_classes(struct objc_abi_symtab* symtab) { uint_fast32_t i; for (i = 0; i < symtab->cls_def_cnt; i++) { struct objc_abi_class* cls = (struct objc_abi_class*)symtab->defs[i]; register_class(cls); register_selectors(cls); register_selectors((struct objc_abi_class*)object_getClass((id)cls)); } for (i = 0; i < symtab->cls_def_cnt; i++) { Class cls = (Class)symtab->defs[i]; if (has_load(cls)) { setup_class(cls); if (cls->info & OBJC_CLASS_INFO_SETUP) call_load(cls); else { if (load_queue == NULL) load_queue = malloc(sizeof(Class)); else load_queue = realloc(load_queue, sizeof(Class) * (load_queue_cnt + 1)); if (load_queue == NULL) OBJC_ERROR( "Not enough memory for load " "queue!"); load_queue[load_queue_cnt++] = cls; } } else cls->info |= OBJC_CLASS_INFO_LOADED; } /* Process load queue */ for (i = 0; i < load_queue_cnt; i++) { setup_class(load_queue[i]); if (load_queue[i]->info & OBJC_CLASS_INFO_SETUP) { call_load(load_queue[i]); load_queue_cnt--; if (load_queue_cnt == 0) { free(load_queue); load_queue = NULL; continue; } load_queue[i] = load_queue[load_queue_cnt]; load_queue = realloc(load_queue, sizeof(Class) * load_queue_cnt); if (load_queue == NULL) OBJC_ERROR("Not enough memory for load queue!"); } } }
static void add_subclass(Class cls) { size_t i; if (cls->superclass->subclass_list == NULL) { if ((cls->superclass->subclass_list = malloc(2 * sizeof(Class))) == NULL) OBJC_ERROR( "Not enough memory for subclass list of " "class %s!", cls->superclass->name); cls->superclass->subclass_list[0] = cls; cls->superclass->subclass_list[1] = Nil; return; } for (i = 0; cls->superclass->subclass_list[i] != Nil; i++) ; cls->superclass->subclass_list = realloc(cls->superclass->subclass_list, (i + 2) * sizeof(Class)); if (cls->superclass->subclass_list == NULL) OBJC_ERROR("Not enough memory for subclass list of class %s\n", cls->superclass->name); cls->superclass->subclass_list[i] = cls; cls->superclass->subclass_list[i + 1] = Nil; }
Property* class_copyPropertyList(Class cls, unsigned int* outCount) { unsigned count = 0; if (cls) { for (struct objc_property_list* propList = cls->properties; propList != NULL; propList = propList->next) { count += propList->count; } } if (outCount) { *outCount = count; } if (count == 0) { return NULL; } Property* outProperties = malloc(count * sizeof(Property)); if (!outProperties) { OBJC_ERROR("Unable to allocate memory for a property list."); } unsigned propertyIndex = 0; for (struct objc_property_list* propList = cls->properties; propList != NULL; propList = propList->next) { for (unsigned i = 0; i < propList->count; ++i) { outProperties[propertyIndex] = &propList->properties[i]; propertyIndex++; } } return outProperties; }
static void objc_global_mutex_new(void) { if (!InitializeCriticalSectionEx(&global_mutex, 0, 0)) OBJC_ERROR("Failed to create global mutex!"); global_mutex_init = YES; }
struct objc_hashtable* objc_hashtable_new(uint32_t size) { struct objc_hashtable *h; uint32_t i; if ((h = malloc(sizeof(struct objc_hashtable))) == NULL) OBJC_ERROR("Not enough memory to allocate hash table!"); h->count = 0; h->last_idx = size - 1; h->data = malloc(size * sizeof(struct objc_hashtable_bucket*)); if (h->data == NULL) OBJC_ERROR("Not enough memory to allocate hash table!"); for (i = 0; i < size; i++) h->data[i] = NULL; return h; }
// Add a method to a class, unconditionally void _class_addMethod(Class cls, SEL sel, IMP newimp, const char* types) { struct objc_method_list* ml; /* FIXME: We need a way to free this at objc_exit() */ if ((ml = malloc(sizeof(struct objc_method_list))) == NULL) OBJC_ERROR("Not enough memory to add a new method!"); objc_global_mutex_lock(); ml->next = cls->methodlist; ml->count = 1; ml->methods[0].sel.uid = sel->uid; ml->methods[0].sel.types = types; ml->methods[0].imp = newimp; cls->methodlist = ml; objc_update_dtable(cls); objc_global_mutex_unlock(); }
void objc_init_static_instances(struct objc_abi_symtab *symtab) { struct objc_abi_static_instances **si; size_t i; /* Check if the class for a static instance became available */ for (i = 0; i < static_instances_cnt; i++) { Class cls = objc_lookup_class(static_instances[i]->class_name); if (cls != Nil) { id *instances; for (instances = static_instances[i]->instances; *instances != nil; instances++) _object_setClass(*instances, cls); static_instances_cnt--; if (static_instances_cnt == 0) { free(static_instances); static_instances = NULL; continue; } static_instances[i] = static_instances[static_instances_cnt]; static_instances = realloc(static_instances, sizeof(struct objc_abi_static_instances*) * static_instances_cnt); if (static_instances == NULL) OBJC_ERROR("Not enough memory for list of " "static instances!"); } } si = (struct objc_abi_static_instances**) symtab->defs[symtab->cls_def_cnt + symtab->cat_def_cnt]; if (si == NULL) return; for (; *si != NULL; si++) { Class cls = objc_lookup_class((*si)->class_name); if (cls != Nil) { id *instances; for (instances = (*si)->instances; *instances != nil; instances++) _object_setClass(*instances, cls); } else { if (static_instances == NULL) static_instances = malloc(sizeof( struct objc_abi_static_instances*)); else static_instances = realloc(static_instances, sizeof(struct objc_abi_static_instances*) * (static_instances_cnt + 1)); if (static_instances == NULL) OBJC_ERROR("Not enough memory for list of " "static instances!"); static_instances[static_instances_cnt++] = *si; } } }
static void insert(struct objc_hashtable *h, const char *key, const void *obj) { uint32_t i, hash, last; struct objc_hashtable_bucket *bucket; hash = objc_hash_string(key); assert(h->count + 1 <= UINT32_MAX / 4); if ((h->count + 1) * 4 / (h->last_idx + 1) >= 3) { struct objc_hashtable_bucket **ndata; uint32_t nsize = (h->last_idx + 1) << 1; assert(nsize > 0); ndata = malloc(nsize * sizeof(struct objc_hashtable_bucket*)); if (ndata == NULL) OBJC_ERROR("Not enough memory to insert into hash " "table!"); for (i = 0; i < nsize; i++) ndata[i] = NULL; for (i = 0; i <= h->last_idx; i++) { if (h->data[i] != NULL) { uint32_t j; last = nsize; for (j = h->data[i]->hash & (nsize - 1); j < last && ndata[j] != NULL; j++); if (j >= last) { last = h->data[i]->hash & (nsize - 1); for (j = 0; j < last && ndata[j] != NULL; j++); } if (j >= last) OBJC_ERROR("No free bucket!"); ndata[j] = h->data[i]; } } free(h->data); h->data = ndata; h->last_idx = nsize - 1; } last = h->last_idx + 1; for (i = hash & h->last_idx; i < last && h->data[i] != NULL; i++); if (i >= last) { last = hash & h->last_idx; for (i = 0; i < last && h->data[i] != NULL; i++); } if (i >= last) OBJC_ERROR("No free bucket!"); if ((bucket = malloc(sizeof(struct objc_hashtable_bucket))) == NULL) OBJC_ERROR("Not enough memory to allocate hash table bucket!"); bucket->key = key; bucket->hash = hash; bucket->obj = obj; h->data[i] = bucket; h->count++; }