?? sendmsg.c
字號:
if (method_list->method_next) __objc_install_methods_in_dtable (class, method_list->method_next); for (i = 0; i < method_list->method_count; i++) { Method_t method = &(method_list->method_list[i]); sarray_at_put_safe (class->dtable, (sidx) method->method_name->sel_id, method->method_imp); }}/* Assumes that __objc_runtime_mutex is locked down. */static void__objc_install_dispatch_table_for_class (Class class){ Class super; /* If the class has not yet had it's class links resolved, we must re-compute all class links */ if(!CLS_ISRESOLV(class)) __objc_resolve_class_links(); super = class->super_class; if (super != 0 && (super->dtable == __objc_uninstalled_dtable)) __objc_install_dispatch_table_for_class (super); /* Allocate dtable if necessary */ if (super == 0) { objc_mutex_lock(__objc_runtime_mutex); class->dtable = sarray_new (__objc_selector_max_index, 0); objc_mutex_unlock(__objc_runtime_mutex); } else class->dtable = sarray_lazy_copy (super->dtable); __objc_install_methods_in_dtable (class, class->methods);}void__objc_update_dispatch_table_for_class (Class class){ Class next; struct sarray *arr; /* not yet installed -- skip it */ if (class->dtable == __objc_uninstalled_dtable) return; objc_mutex_lock(__objc_runtime_mutex); arr = class->dtable; __objc_install_premature_dtable (class); /* someone might require it... */ sarray_free (arr); /* release memory */ /* could have been lazy... */ __objc_install_dispatch_table_for_class (class); if (class->subclass_list) /* Traverse subclasses */ for (next = class->subclass_list; next; next = next->sibling_class) __objc_update_dispatch_table_for_class (next); objc_mutex_unlock(__objc_runtime_mutex);}/* This function adds a method list to a class. This function is typically called by another function specific to the run-time. As such this function does not worry about thread safe issues. This one is only called for categories. Class objects have their methods installed right away, and their selectors are made into SEL's by the function __objc_register_selectors_from_class. */ voidclass_add_method_list (Class class, MethodList_t list){ int i; /* Passing of a linked list is not allowed. Do multiple calls. */ assert (!list->method_next); /* Check for duplicates. */ for (i = 0; i < list->method_count; ++i) { Method_t method = &list->method_list[i]; if (method->method_name) /* Sometimes these are NULL */ { /* This is where selector names are transmogrified to SEL's */ method->method_name = sel_register_typed_name ((const char*)method->method_name, method->method_types); } } /* Add the methods to the class's method list. */ list->method_next = class->methods; class->methods = list; /* Update the dispatch table of class */ __objc_update_dispatch_table_for_class (class);}Method_tclass_get_instance_method(Class class, SEL op){ return search_for_method_in_hierarchy(class, op);}Method_tclass_get_class_method(MetaClass class, SEL op){ return search_for_method_in_hierarchy(class, op);}/* Search for a method starting from the current class up its hierarchy. Return a pointer to the method's method structure if found. NULL otherwise. */ static Method_tsearch_for_method_in_hierarchy (Class cls, SEL sel){ Method_t method = NULL; Class class; if (! sel_is_mapped (sel)) return NULL; /* Scan the method list of the class. If the method isn't found in the list then step to its super class. */ for (class = cls; ((! method) && class); class = class->super_class) method = search_for_method_in_list (class->methods, sel); return method;}/* Given a linked list of method and a method's name. Search for the named method's method structure. Return a pointer to the method's method structure if found. NULL otherwise. */ Method_tsearch_for_method_in_list (MethodList_t list, SEL op){ MethodList_t method_list = list; if (! sel_is_mapped (op)) return NULL; /* If not found then we'll search the list. */ while (method_list) { int i; /* Search the method list. */ for (i = 0; i < method_list->method_count; ++i) { Method_t method = &method_list->method_list[i]; if (method->method_name) if (method->method_name->sel_id == op->sel_id) return method; } /* The method wasn't found. Follow the link to the next list of methods. */ method_list = method_list->method_next; } return NULL;}static retval_t __objc_forward (id object, SEL sel, arglist_t args);/* Forwarding pointers/integers through the normal registers */static id__objc_word_forward (id rcv, SEL op, ...){ void *args, *res; args = __builtin_apply_args (); res = __objc_forward (rcv, op, args); if (res) __builtin_return (res); else return res;}/* Specific routine for forwarding floats/double because of architectural differences on some processors. i386s for example which uses a floating point stack versus general registers for floating point numbers. This forward routine makes sure that GCC restores the proper return values */static double__objc_double_forward (id rcv, SEL op, ...){ void *args, *res; args = __builtin_apply_args (); res = __objc_forward (rcv, op, args); __builtin_return (res);}#if INVISIBLE_STRUCT_RETURNstatic __big#elsestatic id#endif__objc_block_forward (id rcv, SEL op, ...){ void *args, *res; args = __builtin_apply_args (); res = __objc_forward (rcv, op, args); if (res) __builtin_return (res); else#if INVISIBLE_STRUCT_RETURN return (__big) {0};#else return nil;#endif}/* This function is installed in the dispatch table for all methods which are not implemented. Thus, it is called when a selector is not recognized. */static retval_t__objc_forward (id object, SEL sel, arglist_t args){ IMP imp; static SEL frwd_sel = 0; /* !T:SAFE2 */ SEL err_sel; /* first try if the object understands forward:: */ if (!frwd_sel) frwd_sel = sel_get_any_uid("forward::"); if (__objc_responds_to (object, frwd_sel)) { imp = get_imp(object->class_pointer, frwd_sel); return (*imp)(object, frwd_sel, sel, args); } /* If the object recognizes the doesNotRecognize: method then we're going to send it. */ err_sel = sel_get_any_uid ("doesNotRecognize:"); if (__objc_responds_to (object, err_sel)) { imp = get_imp (object->class_pointer, err_sel); return (*imp) (object, err_sel, sel); } /* The object doesn't recognize the method. Check for responding to error:. If it does then sent it. */ { size_t strlen (const char*); char msg[256 + strlen ((const char*)sel_get_name (sel)) + strlen ((const char*)object->class_pointer->name)]; sprintf (msg, "(%s) %s does not recognize %s", (CLS_ISMETA(object->class_pointer) ? "class" : "instance" ), object->class_pointer->name, sel_get_name (sel)); err_sel = sel_get_any_uid ("error:"); if (__objc_responds_to (object, err_sel)) { imp = get_imp (object->class_pointer, err_sel); return (*imp) (object, sel_get_any_uid ("error:"), msg); } /* The object doesn't respond to doesNotRecognize: or error:; Therefore, a default action is taken. */ objc_error (object, OBJC_ERR_UNIMPLEMENTED, "%s\n", msg); return 0; }}void__objc_print_dtable_stats(){ int total = 0; objc_mutex_lock(__objc_runtime_mutex); printf("memory usage: (%s)\n",#ifdef OBJC_SPARSE2 "2-level sparse arrays"#else "3-level sparse arrays"#endif ); printf("arrays: %d = %ld bytes\n", narrays, (long)narrays*sizeof(struct sarray)); total += narrays*sizeof(struct sarray); printf("buckets: %d = %ld bytes\n", nbuckets, (long)nbuckets*sizeof(struct sbucket)); total += nbuckets*sizeof(struct sbucket); printf("idxtables: %d = %ld bytes\n", idxsize, (long)idxsize*sizeof(void*)); total += idxsize*sizeof(void*); printf("-----------------------------------\n"); printf("total: %d bytes\n", total); printf("===================================\n"); objc_mutex_unlock(__objc_runtime_mutex);}/* Returns the uninstalled dispatch table indicator. If a class' dispatch table points to __objc_uninstalled_dtable then that means it needs its dispatch table to be installed. */__inline__struct sarray* objc_get_uninstalled_dtable(){ return __objc_uninstalled_dtable;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -