Differences From Artifact [ae710a7cad]:
- File
src/runtime/class.m
— part of check-in
[e23441b121]
at
2014-05-15 15:17:44
on branch trunk
— Don't declare objc_classname_to_class inline
It is too big already for inlining to make any sense. (user: js, size: 19237) [annotate] [blame] [check-ins using]
To Artifact [79ebd88d66]:
- File
src/runtime/class.m
— part of check-in
[1ebb9eb7b3]
at
2014-05-15 15:32:35
on branch trunk
— Multiple dtable / sparse array improvements
* dtable.m is now the old sparse array, using IMP as type for values and
thus not violating the C standard anymore (functions may not be stored
in void*)
* New sparsearray.m which can work with any size, based on the sparse
array from the fast path of class.m
* Fast path of class.m now uses the new sparsearray.m (user: js, size: 18110) [annotate] [blame] [check-ins using]
︙ | ︙ | |||
21 22 23 24 25 26 27 | #include <string.h> #include <assert.h> #import "runtime.h" #import "runtime-private.h" | < < < < | | | | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | #include <string.h> #include <assert.h> #import "runtime.h" #import "runtime-private.h" static struct objc_hashtable *classes = NULL; static unsigned classes_cnt = 0; static Class *load_queue = NULL; static size_t load_queue_cnt = 0; static struct objc_dtable *empty_dtable = NULL; static unsigned lookups_till_fast_path = 128; static struct objc_sparsearray *fast_path = NULL; static void register_class(struct objc_abi_class *cls) { if (classes == NULL) classes = objc_hashtable_new( objc_hash_string, objc_equal_string, 2); objc_hashtable_set(classes, cls->name, cls); if (empty_dtable == NULL) empty_dtable = objc_dtable_new(); cls->dtable = empty_dtable; cls->metaclass->dtable = empty_dtable; if (strcmp(cls->name, "Protocol") != 0) classes_cnt++; } |
︙ | ︙ | |||
78 79 80 81 82 83 84 | objc_register_selector( (struct objc_abi_selector*)&ml->methods[i]); } Class objc_classname_to_class(const char *name, bool cache) { | | | 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | objc_register_selector( (struct objc_abi_selector*)&ml->methods[i]); } Class objc_classname_to_class(const char *name, bool cache) { Class cls; if (classes == NULL) return Nil; /* * Fast path * |
︙ | ︙ | |||
104 105 106 107 108 109 110 | * * Runtime internal usage does not use the fast path and does not count * as a call into objc_classname_to_class(). The reason for this is * that if the runtime calls into objc_classname_to_class(), it already * has the lock and thus the performance gain would be small, but it * would waste memory. */ | | < < < | < < < < < < | < | | | < < < < < < < < < < < < | < < < < < | < < | < | < | | 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | * * Runtime internal usage does not use the fast path and does not count * as a call into objc_classname_to_class(). The reason for this is * that if the runtime calls into objc_classname_to_class(), it already * has the lock and thus the performance gain would be small, but it * would waste memory. */ if (cache && fast_path != NULL) { cls = objc_sparsearray_get(fast_path, (uintptr_t)name); if (cls != Nil) return cls; } objc_global_mutex_lock(); cls = (Class)((uintptr_t)objc_hashtable_get(classes, name) & ~1); if (cache && fast_path == NULL && --lookups_till_fast_path == 0) fast_path = objc_sparsearray_new(sizeof(uintptr_t)); if (cache && fast_path != NULL) objc_sparsearray_set(fast_path, (uintptr_t)name, cls); objc_global_mutex_unlock(); return cls; } static void call_method(Class cls, const char *method) { struct objc_method_list *ml; SEL selector; |
︙ | ︙ | |||
215 216 217 218 219 220 221 | struct objc_category **cats; unsigned int i; if (!(cls->info & OBJC_CLASS_INFO_DTABLE)) return; if (cls->dtable == empty_dtable) | | | | | | 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 | struct objc_category **cats; unsigned int i; if (!(cls->info & OBJC_CLASS_INFO_DTABLE)) return; if (cls->dtable == empty_dtable) cls->dtable = objc_dtable_new(); if (cls->superclass != Nil) objc_dtable_copy(cls->dtable, cls->superclass->dtable); for (ml = cls->methodlist; ml != NULL; ml = ml->next) for (i = 0; i < ml->count; i++) objc_dtable_set(cls->dtable, (uint32_t)ml->methods[i].sel.uid, ml->methods[i].imp); if ((cats = objc_categories_for_class(cls)) != NULL) { for (i = 0; cats[i] != NULL; i++) { unsigned int j; ml = (cls->info & OBJC_CLASS_INFO_CLASS ? cats[i]->instance_methods : cats[i]->class_methods); for (; ml != NULL; ml = ml->next) for (j = 0; j < ml->count; j++) objc_dtable_set(cls->dtable, (uint32_t)ml->methods[j].sel.uid, ml->methods[j].imp); } } if (cls->subclass_list != NULL) { Class *iter; |
︙ | ︙ | |||
841 842 843 844 845 846 847 | if (rcls->subclass_list != NULL) { free(rcls->subclass_list); rcls->subclass_list = NULL; } if (rcls->dtable != NULL && rcls->dtable != empty_dtable) | | | 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 | if (rcls->subclass_list != NULL) { free(rcls->subclass_list); rcls->subclass_list = NULL; } if (rcls->dtable != NULL && rcls->dtable != empty_dtable) objc_dtable_free(rcls->dtable); rcls->dtable = NULL; if (rcls->superclass != Nil) cls->superclass = rcls->superclass->name; rcls->info &= ~OBJC_CLASS_INFO_SETUP; |
︙ | ︙ | |||
869 870 871 872 873 874 875 | if (strcmp(class_getName(cls), "Protocol") != 0) classes_cnt--; unregister_class(cls); unregister_class(cls->isa); } | < < < < < < < < < < < < < < | 834 835 836 837 838 839 840 841 842 843 844 845 846 847 | if (strcmp(class_getName(cls), "Protocol") != 0) classes_cnt--; unregister_class(cls); unregister_class(cls->isa); } void objc_unregister_all_classes(void) { uint_fast32_t i; if (classes == NULL) return; |
︙ | ︙ | |||
916 917 918 919 920 921 922 | i = UINT_FAST32_MAX; } } assert(classes_cnt == 0); if (empty_dtable != NULL) { | | | | | 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 | i = UINT_FAST32_MAX; } } assert(classes_cnt == 0); if (empty_dtable != NULL) { objc_dtable_free(empty_dtable); empty_dtable = NULL; } objc_sparsearray_free(fast_path); fast_path = NULL; objc_hashtable_free(classes); classes = NULL; } |