bool install_slot(struct objc_object *obj, int offset, IMP method, char * types, uint32_t sel) { //Type must match selector type char * seltypes = types_for_selector(sel); if(safestrcmp(seltypes, types) != 0) { return false; } objc_lock_object(obj); if(SLOTS(obj) == NULL) { SLOTS(obj) = SparseArrayNew(); } struct objc_slot * oldSlot = SparseArrayLookup(SLOTS(obj), sel); if(oldSlot) { if(safestrcmp(types, oldSlot->types) != 0) { objc_unlock_object(obj); return false; } oldSlot->offset = offset; oldSlot->method = method; } else { //We are adding a new slot, not modifying an old one, so we need to //invalidate a load of caches. id object = obj; oldSlot = slot_lookup(&object, sel, nil); struct objc_slot * newslot = calloc(1, sizeof(struct objc_slot)); //TODO: Factor this out into a slot constructor newslot->offset = offset; newslot->method = method; if(types == NULL) { newslot->types = NULL; } else { newslot->types = strdup(types); } if(oldSlot != NULL) { oldSlot->version++; } SparseArrayInsert(SLOTS(obj), sel, newslot); } objc_unlock_object(obj); return true; }
static void collectMethodsForMethodListToSparseArray( struct objc_method_list *list, SparseArray *sarray) { if (NULL != list->next) { collectMethodsForMethodListToSparseArray(list->next, sarray); } for (unsigned i=0 ; i<list->count ; i++) { //fprintf(stderr, "Adding method %s (%d)\n", sel_getName(list->methods[i].selector), PTR_TO_IDX(list->methods[i].selector->name)); SparseArrayInsert(sarray, PTR_TO_IDX(list->methods[i].selector->name), (void*)&list->methods[i]); } }
static void collectMethodsForMethodListToSparseArray( objc_method_list *list, SparseArray *sarray, BOOL recurse) { if (recurse && (NULL != list->next)) { collectMethodsForMethodListToSparseArray(list->next, sarray, YES); } for (unsigned i=0 ; i<list->size ; i++) { SparseArrayInsert(sarray, list->list[i].selector, (void*)&list->list[i]); } }