?? init.c
字號:
int module_initialized = 1; for (statics_in_module = (*cell)->head; *statics_in_module; statics_in_module++) { struct objc_static_instances *statics = *statics_in_module; Class class = objc_lookup_class (statics->class_name); if (! class) module_initialized = 0; /* Actually, the static's class_pointer will be NULL when we haven't been here before. However, the comparison is to be reminded of taking into account class posing and to think about possible semantics... */ else if (class != statics->instances[0]->class_pointer) { id *inst; for (inst = &statics->instances[0]; *inst; inst++) { (*inst)->class_pointer = class; /* ??? Make sure the object will not be freed. With refcounting, invoke `-retain'. Without refcounting, do nothing and hope that `-free' will never be invoked. */ /* ??? Send the object an `-initStatic' or something to that effect now or later on? What are the semantics of statically allocated instances, besides the trivial NXConstantString, anyway? */ } } } if (module_initialized) { /* Remove this module from the uninitialized list. */ struct objc_list *this = *cell; *cell = this->tail; objc_free (this); } else cell = &(*cell)->tail; } objc_mutex_unlock (__objc_runtime_mutex);} /* objc_init_statics *//* This function is called by constructor functions generated for each module compiled. (_GLOBAL_$I$...) The purpose of this function is to gather the module pointers so that they may be processed by the initialization routines as soon as possible. */void__objc_exec_class (Module_t module){ /* Have we processed any constructors previously? This flag is used to indicate that some global data structures need to be built. */ static BOOL previous_constructors = 0; static struct objc_list *unclaimed_categories = 0; /* The symbol table (defined in objc-api.h) generated by gcc */ Symtab_t symtab = module->symtab; /* The statics in this module */ struct objc_static_instances **statics = symtab->defs[symtab->cls_def_cnt + symtab->cat_def_cnt]; /* Entry used to traverse hash lists */ struct objc_list **cell; /* The table of selector references for this module */ SEL selectors = symtab->refs; /* dummy counter */ int i; DEBUG_PRINTF ("received module: %s\n", module->name); /* check gcc version */ init_check_module_version (module); /* On the first call of this routine, initialize some data structures. */ if (! previous_constructors) { /* Initialize thread-safe system */ __objc_init_thread_system (); __objc_runtime_threads_alive = 1; __objc_runtime_mutex = objc_mutex_allocate (); __objc_init_selector_tables (); __objc_init_class_tables (); __objc_init_dispatch_tables (); __objc_class_tree_list = list_cons (NULL, __objc_class_tree_list); __objc_load_methods = objc_hash_new (128, (hash_func_type)objc_hash_ptr, objc_compare_ptrs); previous_constructors = 1; } /* Save the module pointer for later processing. (not currently used) */ objc_mutex_lock (__objc_runtime_mutex); __objc_module_list = list_cons (module, __objc_module_list); /* Replace referenced selectors from names to SEL's. */ if (selectors) { for (i = 0; selectors[i].sel_id; ++i) { const char *name, *type; name = (char *) selectors[i].sel_id; type = (char *) selectors[i].sel_types; /* Constructors are constant static data so we can safely store pointers to them in the runtime structures. is_const == YES */ __sel_register_typed_name (name, type, (struct objc_selector *) &(selectors[i]), YES); } } /* Parse the classes in the load module and gather selector information. */ DEBUG_PRINTF ("gathering selectors from module: %s\n", module->name); for (i = 0; i < symtab->cls_def_cnt; ++i) { Class class = (Class) symtab->defs[i]; const char *superclass = (char *) class->super_class; /* Make sure we have what we think. */ assert (CLS_ISCLASS (class)); assert (CLS_ISMETA (class->class_pointer)); DEBUG_PRINTF ("phase 1, processing class: %s\n", class->name); /* Initialize the subclass list to be NULL. In some cases it isn't and this crashes the program. */ class->subclass_list = NULL; /* Store the class in the class table and assign class numbers. */ __objc_add_class_to_hash (class); /* Register all of the selectors in the class and meta class. */ __objc_register_selectors_from_class (class); __objc_register_selectors_from_class ((Class) class->class_pointer); /* Install the fake dispatch tables */ __objc_install_premature_dtable (class); __objc_install_premature_dtable (class->class_pointer); /* Register the instance methods as class methods, this is only done for root classes. */ __objc_register_instance_methods_to_class (class); if (class->protocols) __objc_init_protocols (class->protocols); /* Check to see if the superclass is known in this point. If it's not add the class to the unresolved_classes list. */ if (superclass && ! objc_lookup_class (superclass)) unresolved_classes = list_cons (class, unresolved_classes); } /* Process category information from the module. */ for (i = 0; i < symtab->cat_def_cnt; ++i) { Category_t category = symtab->defs[i + symtab->cls_def_cnt]; Class class = objc_lookup_class (category->class_name); /* If the class for the category exists then append its methods. */ if (class) { DEBUG_PRINTF ("processing categories from (module,object): %s, %s\n", module->name, class->name); /* Do instance methods. */ if (category->instance_methods) class_add_method_list (class, category->instance_methods); /* Do class methods. */ if (category->class_methods) class_add_method_list ((Class) class->class_pointer, category->class_methods); if (category->protocols) { __objc_init_protocols (category->protocols); __objc_class_add_protocols (class, category->protocols); } /* Register the instance methods as class methods, this is only done for root classes. */ __objc_register_instance_methods_to_class (class); } else { /* The object to which the category methods belong can't be found. Save the information. */ unclaimed_categories = list_cons (category, unclaimed_categories); } } if (statics) uninitialized_statics = list_cons (statics, uninitialized_statics); if (uninitialized_statics) objc_init_statics (); /* Scan the unclaimed category hash. Attempt to attach any unclaimed categories to objects. */ for (cell = &unclaimed_categories; *cell; ) { Category_t category = (*cell)->head; Class class = objc_lookup_class (category->class_name); if (class) { DEBUG_PRINTF ("attaching stored categories to object: %s\n", class->name); list_remove_head (cell); if (category->instance_methods) class_add_method_list (class, category->instance_methods); if (category->class_methods) class_add_method_list ((Class) class->class_pointer, category->class_methods); if (category->protocols) { __objc_init_protocols (category->protocols); __objc_class_add_protocols (class, category->protocols); } /* Register the instance methods as class methods, this is only done for root classes. */ __objc_register_instance_methods_to_class (class); } else cell = &(*cell)->tail; } if (unclaimed_proto_list && objc_lookup_class ("Protocol")) { list_mapcar (unclaimed_proto_list, (void (*) (void *))__objc_init_protocols); list_free (unclaimed_proto_list); unclaimed_proto_list = 0; } objc_send_load (); objc_mutex_unlock (__objc_runtime_mutex);}static voidobjc_send_load (void){ if (! __objc_module_list) return; /* Try to find out if all the classes loaded so far also have their superclasses known to the runtime. We suppose that the objects that are allocated in the +load method are in general of a class declared in the same module. */ if (unresolved_classes) { Class class = unresolved_classes->head; while (objc_lookup_class ((char *) class->super_class)) { list_remove_head (&unresolved_classes); if (unresolved_classes) class = unresolved_classes->head; else break; } /* If we still have classes for whom we don't have yet their super classes known to the runtime we don't send the +load messages. */ if (unresolved_classes) return; } /* Special check to allow creating and sending messages to constant strings in +load methods. If these classes are not yet known, even if all the other classes are known, delay sending of +load. */ if (! objc_lookup_class ("NXConstantString") || ! objc_lookup_class ("Object")) return; /* Iterate over all modules in the __objc_module_list and call on them the __objc_create_classes_tree function. This function creates a tree of classes that resembles the class hierarchy. */ list_mapcar (__objc_module_list, (void (*) (void *)) __objc_create_classes_tree); while (__objc_class_tree_list) {#ifdef DEBUG objc_preorder_traverse (__objc_class_tree_list->head, 0, __objc_tree_print);#endif objc_preorder_traverse (__objc_class_tree_list->head, 0, __objc_send_load); objc_postorder_traverse (__objc_class_tree_list->head, 0, __objc_destroy_class_tree_node); list_remove_head (&__objc_class_tree_list); } list_mapcar (__objc_module_list, (void (*) (void *)) __objc_call_callback); list_free (__objc_module_list); __objc_module_list = NULL;}static void__objc_create_classes_tree (Module_t module){ /* The runtime mutex is locked in this point */ Symtab_t symtab = module->symtab; int i; /* Iterate thru classes defined in this module and insert them in the classes tree hierarchy. */ for (i = 0; i < symtab->cls_def_cnt; i++) { Class class = (Class) symtab->defs[i]; objc_tree_insert_class (class); }}static void__objc_call_callback (Module_t module){ /* The runtime mutex is locked in this point. */ Symtab_t symtab = module->symtab; int i; /* Iterate thru classes defined in this module and call the callback for each one. */ for (i = 0; i < symtab->cls_def_cnt; i++) { Class class = (Class) symtab->defs[i]; /* Call the _objc_load_callback for this class. */ if (_objc_load_callback) _objc_load_callback (class, 0); } /* Call the _objc_load_callback for categories. Don't register the instance methods as class methods for categories to root classes since they were already added in the class. */ for (i = 0; i < symtab->cat_def_cnt; i++) { Category_t category = symtab->defs[i + symtab->cls_def_cnt]; Class class = objc_lookup_class (category->class_name); if (_objc_load_callback) _objc_load_callback (class, category); }}/* Sanity check the version of gcc used to compile `module'. */static voidinit_check_module_version (Module_t module){ if ((module->version != OBJC_VERSION) || (module->size != sizeof (Module))) { int code; if (module->version > OBJC_VERSION) code = OBJC_ERR_OBJC_VERSION; else if (module->version < OBJC_VERSION) code = OBJC_ERR_GCC_VERSION; else code = OBJC_ERR_MODULE_SIZE; objc_error (nil, code, "Module %s version %d doesn't match runtime %d\n", module->name, (int)module->version, OBJC_VERSION); }}static void__objc_init_protocols (struct objc_protocol_list *protos){ size_t i; static Class proto_class = 0; if (! protos) return; objc_mutex_lock (__objc_runtime_mutex); if (! proto_class) proto_class = objc_lookup_class ("Protocol"); if (! proto_class) { unclaimed_proto_list = list_cons (protos, unclaimed_proto_list); objc_mutex_unlock (__objc_runtime_mutex); return; }#if 0 assert (protos->next == 0); /* only single ones allowed */#endif for (i = 0; i < protos->count; i++) { struct objc_protocol *aProto = protos->list[i]; if (((size_t)aProto->class_pointer) == PROTOCOL_VERSION) { /* assign class pointer */ aProto->class_pointer = proto_class; /* init super protocols */ __objc_init_protocols (aProto->protocol_list); } else if (protos->list[i]->class_pointer != proto_class) { objc_error (nil, OBJC_ERR_PROTOCOL_VERSION, "Version %d doesn't match runtime protocol version %d\n", (int) ((char *) protos->list[i]->class_pointer - (char *) 0), PROTOCOL_VERSION); } } objc_mutex_unlock (__objc_runtime_mutex);}static void__objc_class_add_protocols (Class class, struct objc_protocol_list *protos){ /* Well... */ if (! protos) return; /* Add it... */ protos->next = class->protocols; class->protocols = protos;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -