Comment: | Multiple dtable / sparse array improvements
* dtable.m is now the old sparse array, using IMP as type for values and |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
1ebb9eb7b3b52c548f98eb4e6a9a5222 |
User & Date: | js on 2014-05-15 15:32:35 |
Other Links: | manifest | tags |
2014-05-15
| ||
15:32 | Fix a few instances of signed vs. unsigned check-in: 7f0359ce68 user: js tags: trunk | |
15:32 | Multiple dtable / sparse array improvements check-in: 1ebb9eb7b3 user: js tags: trunk | |
15:17 | Don't declare objc_classname_to_class inline check-in: e23441b121 user: js tags: trunk | |
Modified src/OFObject.m from [a836174d3d] to [31f7e1ca7d].
︙ | ︙ | |||
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 | @implementation OFObject + (void)load { #if !defined(OF_APPLE_RUNTIME) || defined(__OBJC2__) objc_setUncaughtExceptionHandler(uncaughtExceptionHandler); #endif objc_setForwardHandler((void*)&of_forward, (void*)&of_forward_stret); #ifdef HAVE_OBJC_ENUMERATIONMUTATION objc_setEnumerationMutationHandler(enumerationMutationHandler); #endif #if defined(HAVE_ARC4RANDOM) of_hash_seed = arc4random(); | > > > > | 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 | @implementation OFObject + (void)load { #if !defined(OF_APPLE_RUNTIME) || defined(__OBJC2__) objc_setUncaughtExceptionHandler(uncaughtExceptionHandler); #endif #if defined(OF_APPLE_RUNTIME) objc_setForwardHandler((void*)&of_forward, (void*)&of_forward_stret); #else objc_setForwardHandler((IMP)&of_forward, (IMP)&of_forward_stret); #endif #ifdef HAVE_OBJC_ENUMERATIONMUTATION objc_setEnumerationMutationHandler(enumerationMutationHandler); #endif #if defined(HAVE_ARC4RANDOM) of_hash_seed = arc4random(); |
︙ | ︙ |
Modified src/runtime/Makefile from [9343c57ff2] to [19c7e25279].
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | include ../../extra.mk SUBDIRS = lookup-asm STATIC_PIC_LIB_NOINST = ${RUNTIME_LIB_A} STATIC_LIB_NOINST = ${RUNTIME_A} SRCS = arc.m \ category.m \ class.m \ exception.m \ hashtable.m \ init.m \ lookup.m \ property.m \ protocol.m \ selector.m \ | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | include ../../extra.mk SUBDIRS = lookup-asm STATIC_PIC_LIB_NOINST = ${RUNTIME_LIB_A} STATIC_LIB_NOINST = ${RUNTIME_A} SRCS = arc.m \ category.m \ class.m \ dtable.m \ exception.m \ hashtable.m \ init.m \ lookup.m \ property.m \ protocol.m \ selector.m \ |
︙ | ︙ |
Modified src/runtime/class.m from [ae710a7cad] to [79ebd88d66].
︙ | ︙ | |||
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; } |
Added src/runtime/dtable.m version [397b45eb7b].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 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 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 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 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 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 215 216 217 | /* * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 * Jonathan Schleifer <js@webkeks.org> * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in * the packaging of this file. * * Alternatively, it may be distributed under the terms of the GNU General * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #include "config.h" #include <stdio.h> #include <stdlib.h> #import "runtime.h" #import "runtime-private.h" static struct objc_dtable_level2 *empty_level2 = NULL; #ifdef OF_SELUID24 static struct objc_dtable_level3 *empty_level3 = NULL; #endif static void init(void) { uint_fast16_t i; empty_level2 = malloc(sizeof(struct objc_dtable_level2)); if (empty_level2 == NULL) OBJC_ERROR("Not enough memory to allocate dtable!"); #ifdef OF_SELUID24 empty_level3 = malloc(sizeof(struct objc_dtable_level3)); if (empty_level3 == NULL) OBJC_ERROR("Not enough memory to allocate dtable!"); #endif #ifdef OF_SELUID24 for (i = 0; i < 256; i++) { empty_level2->buckets[i] = empty_level3; empty_level3->buckets[i] = (IMP)0; } #else for (i = 0; i < 256; i++) empty_level2->buckets[i] = (IMP)0; #endif } struct objc_dtable* objc_dtable_new(void) { struct objc_dtable *dtable; uint_fast16_t i; #ifdef OF_SELUID24 if (empty_level2 == NULL || empty_level3 == NULL) init(); #else if (empty_level2 == NULL) init(); #endif if ((dtable = malloc(sizeof(struct objc_dtable))) == NULL) OBJC_ERROR("Not enough memory to allocate dtable!"); for (i = 0; i < 256; i++) dtable->buckets[i] = empty_level2; return dtable; } void objc_dtable_copy(struct objc_dtable *dst, struct objc_dtable *src) { uint_fast16_t i, j; #ifdef OF_SELUID24 uint_fast16_t k; #endif uint32_t idx; for (i = 0; i < 256; i++) { if (src->buckets[i] == empty_level2) continue; #ifdef OF_SELUID24 for (j = 0; j < 256; j++) { if (src->buckets[i]->buckets[j] == empty_level3) continue; for (k = 0; k < 256; k++) { IMP obj; obj = src->buckets[i]->buckets[j]->buckets[k]; if (obj == (IMP)0) continue; idx = (uint32_t) (((uint32_t)i << 16) | (j << 8) | k); objc_dtable_set(dst, idx, obj); } } #else for (j = 0; j < 256; j++) { IMP obj; obj = src->buckets[i]->buckets[j]; if (obj == (IMP)0) continue; idx = (uint32_t)((i << 8) | j); objc_dtable_set(dst, idx, obj); } #endif } } void objc_dtable_set(struct objc_dtable *dtable, uint32_t idx, IMP obj) { #ifdef OF_SELUID24 uint8_t i = idx >> 16; uint8_t j = idx >> 8; uint8_t k = idx; #else uint8_t i = idx >> 8; uint8_t j = idx; #endif if (dtable->buckets[i] == empty_level2) { struct objc_dtable_level2 *level2; uint_fast16_t l; level2 = malloc(sizeof(struct objc_dtable_level2)); if (level2 == NULL) OBJC_ERROR("Not enough memory to insert into dtable!"); for (l = 0; l < 256; l++) #ifdef OF_SELUID24 level2->buckets[l] = empty_level3; #else level2->buckets[l] = (IMP)0; #endif dtable->buckets[i] = level2; } #ifdef OF_SELUID24 if (dtable->buckets[i]->buckets[j] == empty_level3) { struct objc_dtable_level3 *level3; uint_fast16_t l; level3 = malloc(sizeof(struct objc_dtable_level3)); if (level3 == NULL) OBJC_ERROR("Not enough memory to insert into dtable!"); for (l = 0; l < 256; l++) level3->buckets[l] = (IMP)0; dtable->buckets[i]->buckets[j] = level3; } dtable->buckets[i]->buckets[j]->buckets[k] = obj; #else dtable->buckets[i]->buckets[j] = obj; #endif } void objc_dtable_free(struct objc_dtable *dtable) { uint_fast16_t i; #ifdef OF_SELUID24 uint_fast16_t j; #endif for (i = 0; i < 256; i++) { if (dtable->buckets[i] == empty_level2) continue; #ifdef OF_SELUID24 for (j = 0; j < 256; j++) if (dtable->buckets[i]->buckets[j] != empty_level3) free(dtable->buckets[i]->buckets[j]); #endif free(dtable->buckets[i]); } free(dtable); } void objc_dtable_cleanup(void) { if (empty_level2 != NULL) free(empty_level2); #ifdef OF_SELUID24 if (empty_level3 != NULL) free(empty_level3); #endif empty_level2 = NULL; #ifdef OF_SELUID24 empty_level3 = NULL; #endif } |
Modified src/runtime/init.m from [e94f6f1b19] to [297f1bd347].
︙ | ︙ | |||
37 38 39 40 41 42 43 | { objc_global_mutex_lock(); objc_unregister_all_categories(); objc_unregister_all_classes(); objc_unregister_all_selectors(); objc_forget_pending_static_instances(); | | | 37 38 39 40 41 42 43 44 45 46 47 48 | { objc_global_mutex_lock(); objc_unregister_all_categories(); objc_unregister_all_classes(); objc_unregister_all_selectors(); objc_forget_pending_static_instances(); objc_dtable_cleanup(); objc_global_mutex_unlock(); objc_global_mutex_free(); } |
Modified src/runtime/lookup.m from [cccd16e367] to [c4fa11142c].
︙ | ︙ | |||
19 20 21 22 23 24 25 | #include <stdio.h> #include <stdlib.h> #import "runtime.h" #import "runtime-private.h" #import "macros.h" | | | | | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | #include <stdio.h> #include <stdlib.h> #import "runtime.h" #import "runtime-private.h" #import "macros.h" static IMP forward_handler = (IMP)0; static IMP forward_handler_stret = (IMP)0; static IMP common_method_not_found(id obj, SEL sel, IMP (*lookup)(id, SEL), IMP forward) { /* * obj might be a dummy object (see class_getMethodImplementation), so * don't access obj directly unless it's a class! */ bool is_class = object_getClass(obj)->info & OBJC_CLASS_INFO_METACLASS; |
︙ | ︙ | |||
85 86 87 88 89 90 91 | class_getName(object_getClass(obj)), sel_getName(sel)); return lookup(obj, sel); } } | | | 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | class_getName(object_getClass(obj)), sel_getName(sel)); return lookup(obj, sel); } } if (forward != (IMP)0) return forward; OBJC_ERROR("Selector %c[%s] is not implemented for class %s!", (is_class ? '+' : '-'), sel_getName(sel), object_getClassName(obj)); } IMP |
︙ | ︙ | |||
107 108 109 110 111 112 113 | objc_method_not_found_stret(id obj, SEL sel) { return common_method_not_found(obj, sel, objc_msg_lookup_stret, forward_handler_stret); } void | | | | < | | 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 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | objc_method_not_found_stret(id obj, SEL sel) { return common_method_not_found(obj, sel, objc_msg_lookup_stret, forward_handler_stret); } void objc_setForwardHandler(IMP forward, IMP forward_stret) { forward_handler = forward; forward_handler_stret = forward_stret; } bool class_respondsToSelector(Class cls, SEL sel) { if (cls == Nil) return false; return (objc_dtable_get(cls->dtable, (uint32_t)sel->uid) != (IMP)0); } #ifndef OF_ASM_LOOKUP static id nil_method(id self, SEL _cmd) { return nil; } static OF_INLINE IMP common_lookup(id obj, SEL sel, IMP (*not_found)(id, SEL)) { IMP imp; if (obj == nil) return (IMP)nil_method; imp = objc_dtable_get(object_getClass(obj)->dtable, (uint32_t)sel->uid); if (imp == (IMP)0) return not_found(obj, sel); return imp; } IMP objc_msg_lookup(id obj, SEL sel) |
︙ | ︙ | |||
167 168 169 170 171 172 173 | IMP (*not_found)(id, SEL)) { IMP imp; if (super->self == nil) return (IMP)nil_method; | | | | 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | IMP (*not_found)(id, SEL)) { IMP imp; if (super->self == nil) return (IMP)nil_method; imp = objc_dtable_get(super->cls->dtable, (uint32_t)sel->uid); if (imp == (IMP)0) return not_found(super->self, sel); return imp; } IMP objc_msg_lookup_super(struct objc_super *super, SEL sel) |
︙ | ︙ |
Modified src/runtime/runtime-private.h from [fa7e7433b3] to [bdd53fa1db].
︙ | ︙ | |||
99 100 101 102 103 104 105 | uint32_t (*hash)(const void *key); bool (*equal)(const void *key1, const void *key2); uint32_t count, size; struct objc_hashtable_bucket **data; }; struct objc_sparsearray { | | > > > > > | | < < < | < < > > | < | 99 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 | uint32_t (*hash)(const void *key); bool (*equal)(const void *key1, const void *key2); uint32_t count, size; struct objc_hashtable_bucket **data; }; struct objc_sparsearray { struct objc_sparsearray_data { void *next[256]; } *data; uint_fast8_t index_size; }; struct objc_dtable { struct objc_dtable_level2 { #ifdef OF_SELUID24 struct objc_dtable_level3 { IMP buckets[256]; } *buckets[256]; #else IMP buckets[256]; #endif } *buckets[256]; }; extern void objc_register_all_categories(struct objc_abi_symtab*); extern struct objc_category** objc_categories_for_class(Class); extern void objc_unregister_all_categories(void); extern void objc_initialize_class(Class); extern void objc_update_dtable(Class); extern void objc_register_all_classes(struct objc_abi_symtab*); |
︙ | ︙ | |||
138 139 140 141 142 143 144 | const void*); extern void* objc_hashtable_get(struct objc_hashtable*, const void*); extern void objc_hashtable_delete(struct objc_hashtable*, const void*); extern void objc_hashtable_free(struct objc_hashtable *h); extern void objc_register_selector(struct objc_abi_selector*); extern void objc_register_all_selectors(struct objc_abi_symtab*); extern void objc_unregister_all_selectors(void); | | < | | < > > > > | | | | | | 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 | const void*); extern void* objc_hashtable_get(struct objc_hashtable*, const void*); extern void objc_hashtable_delete(struct objc_hashtable*, const void*); extern void objc_hashtable_free(struct objc_hashtable *h); extern void objc_register_selector(struct objc_abi_selector*); extern void objc_register_all_selectors(struct objc_abi_symtab*); extern void objc_unregister_all_selectors(void); extern struct objc_sparsearray *objc_sparsearray_new(uint_fast8_t); extern void *objc_sparsearray_get(struct objc_sparsearray*, uintptr_t); extern void objc_sparsearray_set(struct objc_sparsearray*, uintptr_t, void*); extern void objc_sparsearray_free(struct objc_sparsearray*); extern struct objc_dtable* objc_dtable_new(void); extern void objc_dtable_copy(struct objc_dtable*, struct objc_dtable*); extern void objc_dtable_set(struct objc_dtable*, uint32_t, IMP); extern void objc_dtable_free(struct objc_dtable*); extern void objc_dtable_cleanup(void); extern void objc_init_static_instances(struct objc_abi_symtab*); extern void objc_forget_pending_static_instances(void); extern void __objc_exec_class(struct objc_abi_module*); #ifdef OF_HAVE_THREADS extern void objc_global_mutex_lock(void); extern void objc_global_mutex_unlock(void); extern void objc_global_mutex_free(void); #else # define objc_global_mutex_lock() # define objc_global_mutex_unlock() # define objc_global_mutex_free() #endif static inline IMP objc_dtable_get(const struct objc_dtable *dtable, uint32_t idx) { #ifdef OF_SELUID24 uint8_t i = idx >> 16; uint8_t j = idx >> 8; uint8_t k = idx; return dtable->buckets[i]->buckets[j]->buckets[k]; #else uint8_t i = idx >> 8; uint8_t j = idx; return dtable->buckets[i]->buckets[j]; #endif } #if defined(__ELF__) # if defined(__x86_64__) || defined(__amd64__) || defined(__i386__) || \ defined(__ppc__) || defined(__PPC__) || defined(__arm__) || \ defined(__ARM__) |
︙ | ︙ |
Modified src/runtime/runtime.h from [e5c437ae29] to [eb23c8ebea].
︙ | ︙ | |||
57 58 59 60 61 62 63 | Class superclass; const char *name; unsigned long version; unsigned long info; long instance_size; struct objc_ivar_list *ivars; struct objc_method_list *methodlist; | | | 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | Class superclass; const char *name; unsigned long version; unsigned long info; long instance_size; struct objc_ivar_list *ivars; struct objc_method_list *methodlist; struct objc_dtable *dtable; Class *subclass_list; void *sibling_class; struct objc_protocol_list *protocols; void *gc_object_type; unsigned long abi_version; int32_t **ivar_offsets; struct objc_property_list *properties; |
︙ | ︙ | |||
213 214 215 216 217 218 219 | extern const char* object_getClassName(id); extern const char* protocol_getName(Protocol*); extern bool protocol_isEqual(Protocol*, Protocol*); extern bool protocol_conformsToProtocol(Protocol*, Protocol*); extern void objc_exit(void); extern objc_uncaught_exception_handler objc_setUncaughtExceptionHandler( objc_uncaught_exception_handler); | | | 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 | extern const char* object_getClassName(id); extern const char* protocol_getName(Protocol*); extern bool protocol_isEqual(Protocol*, Protocol*); extern bool protocol_conformsToProtocol(Protocol*, Protocol*); extern void objc_exit(void); extern objc_uncaught_exception_handler objc_setUncaughtExceptionHandler( objc_uncaught_exception_handler); extern void objc_setForwardHandler(IMP, IMP); extern id objc_autorelease(id); extern void* objc_autoreleasePoolPush(void); extern void objc_autoreleasePoolPop(void*); extern id _objc_rootAutorelease(id); /* Used by the compiler, but can be called manually. */ extern IMP objc_msg_lookup(id, SEL); extern IMP objc_msg_lookup_stret(id, SEL); |
︙ | ︙ |
Modified src/runtime/selector.m from [c556b01892] to [c0034eeff2].
︙ | ︙ | |||
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | #import "runtime.h" #import "runtime-private.h" #import "macros.h" #ifdef OF_SELUID24 # define SEL_MAX 0xFFFFFF #else # define SEL_MAX 0xFFFF #endif static struct objc_hashtable *selectors = NULL; static uint32_t selectors_cnt = 0; static struct objc_sparsearray *selector_names = NULL; static void **free_list = NULL; static size_t free_list_cnt = 0; | > > | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | #import "runtime.h" #import "runtime-private.h" #import "macros.h" #ifdef OF_SELUID24 # define SEL_MAX 0xFFFFFF # define SEL_SIZE 3 #else # define SEL_MAX 0xFFFF # define SEL_SIZE 2 #endif static struct objc_hashtable *selectors = NULL; static uint32_t selectors_cnt = 0; static struct objc_sparsearray *selector_names = NULL; static void **free_list = NULL; static size_t free_list_cnt = 0; |
︙ | ︙ | |||
51 52 53 54 55 56 57 | objc_hash_string, objc_equal_string, 2); else if ((rsel = objc_hashtable_get(selectors, sel->name)) != NULL) { ((struct objc_selector*)sel)->uid = rsel->uid; return; } if (selector_names == NULL) | | | | 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | objc_hash_string, objc_equal_string, 2); else if ((rsel = objc_hashtable_get(selectors, sel->name)) != NULL) { ((struct objc_selector*)sel)->uid = rsel->uid; return; } if (selector_names == NULL) selector_names = objc_sparsearray_new(SEL_SIZE); name = sel->name; rsel = (struct objc_selector*)sel; rsel->uid = selectors_cnt++; objc_hashtable_set(selectors, name, rsel); objc_sparsearray_set(selector_names, (uint32_t)rsel->uid, (void*)name); } SEL sel_registerName(const char *name) { const struct objc_abi_selector *rsel; struct objc_abi_selector *sel; |
︙ | ︙ |
Modified src/runtime/sparsearray.m from [a445e7d9ad] to [8658c862e5].
︙ | ︙ | |||
18 19 20 21 22 23 24 | #include <stdio.h> #include <stdlib.h> #import "runtime.h" #import "runtime-private.h" | | < | < | < < > | < | < < | < | < | < < < < < > | | < < < < > | | | < < < < < < < < < < < | | | < | | < < < < < < < < < | < < < | < < < < < < | < | < < | < | < < < < | | < | < < | < < | < < < | < < < < < | < < | < < | < < | | | < < | < < < < < < | < < < < < | < | < < < < < < < < < < < < < < < | | < < < < | | < | < < < | < | < | | < | < < < < | < < < < | 18 19 20 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 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | #include <stdio.h> #include <stdlib.h> #import "runtime.h" #import "runtime-private.h" struct objc_sparsearray* objc_sparsearray_new(uint_fast8_t index_size) { struct objc_sparsearray *sparsearray; if ((sparsearray = calloc(1, sizeof(*sparsearray))) == NULL) OBJC_ERROR("Failed to allocate memory for sparse array!"); if ((sparsearray->data = calloc(1, sizeof(*sparsearray->data))) == NULL) OBJC_ERROR("Failed to allocate memory for sparse array!"); sparsearray->index_size = index_size; return sparsearray; } void* objc_sparsearray_get(struct objc_sparsearray *sparsearray, uintptr_t idx) { struct objc_sparsearray_data *iter = sparsearray->data; uint_fast8_t i; for (i = 0; i < sparsearray->index_size - 1; i++) { uintptr_t j = (idx >> ((sparsearray->index_size - i - 1) * 8)) & 0xFF; if ((iter = iter->next[j]) == NULL) return NULL; } return iter->next[idx & 0xFF]; } void objc_sparsearray_set(struct objc_sparsearray *sparsearray, uintptr_t idx, void *value) { struct objc_sparsearray_data *iter = sparsearray->data; uint_fast8_t i; for (i = 0; i < sparsearray->index_size - 1; i++) { uintptr_t j = (idx >> ((sparsearray->index_size - i - 1) * 8)) & 0xFF; if (iter->next[j] == NULL) if ((iter->next[j] = calloc(1, sizeof(struct objc_sparsearray_data))) == NULL) OBJC_ERROR("Failed to allocate memory for " "sparse array!"); iter = iter->next[j]; } iter->next[idx & 0xFF] = value; } static void free_sparsearray_data(struct objc_sparsearray_data *data, uint_fast8_t depth) { uint_fast16_t i; if (data == NULL || depth == 0) return; for (i = 0; i < 256; i++) free_sparsearray_data(data->next[i], depth - 1); free(data); } void objc_sparsearray_free(struct objc_sparsearray *sparsearray) { free_sparsearray_data(sparsearray->data, sparsearray->index_size); free(sparsearray); } |