From 314a4167caf0c20642294f711a140efd30573ac6 Mon Sep 17 00:00:00 2001 From: David Chisnall Date: Fri, 23 Mar 2018 11:46:01 +0000 Subject: [PATCH] Remove low memory profile. This hasn't been tested for a long time and probably doesn't work. --- CMakeLists.txt | 5 - dtable.c | 266 ------------------------------------------------- 2 files changed, 271 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6d66c5e..26be035 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -94,11 +94,6 @@ set(ENABLE_TRACING FALSE CACHE BOOL if (ENABLE_TRACING) add_definitions(-DWITH_TRACING=1) endif (ENABLE_TRACING) -set(LOW_MEMORY FALSE CACHE BOOL - "Enable low-memory profile *HIGHLY EXPERIMENTAL*") -if (LOW_MEMORY) - add_definitions(-D__OBJC_LOW_MEMORY__) -endif () set(BOEHM_GC FALSE CACHE BOOL "Enable garbage collection support (not recommended)") diff --git a/dtable.c b/dtable.c index b407cd3..36ba490 100644 --- a/dtable.c +++ b/dtable.c @@ -160,270 +160,6 @@ static void collectMethodsForMethodListToSparseArray( } -#ifdef __OBJC_LOW_MEMORY__ - -struct objc_dtable -{ - struct cache_line - { - uint32_t idx; - uint32_t version; - struct objc_slot *slot; - } cache[8]; - mutex_t lock; - struct objc_slot **slots; - int slot_count; - int slot_size; - Class cls; -}; - -static void update_dtable(dtable_t dtable); - -PRIVATE void init_dispatch_tables () -{ - INIT_LOCK(initialize_lock); -} - -Class class_getSuperclass(Class); - - -static dtable_t create_dtable_for_class(Class class, dtable_t root_dtable) -{ - // Don't create a dtable for a class that already has one - if (classHasDtable(class)) { return dtable_for_class(class); } - - LOCK_RUNTIME_FOR_SCOPE(); - - // Make sure that another thread didn't create the dtable while we were - // waiting on the lock. - if (classHasDtable(class)) { return dtable_for_class(class); } - - // Allocate the dtable - dtable_t dtable = calloc(1, sizeof(struct objc_dtable)); - dtable->cls = class; - INIT_LOCK(dtable->lock); - - // Initialise it - update_dtable(dtable); - - return dtable; -} - - -PRIVATE void objc_resize_dtables(uint32_t newSize) -{ - if (1< newSize) { return; } - dtable_depth <<= 1; -} - -#define HASH_UID(uid) ((uid >> 2) & 7) - -static struct objc_slot* check_cache(dtable_t dtable, uint32_t uid) -{ - int i = HASH_UID(uid); - volatile struct cache_line *cache = &dtable->cache[i]; - int32_t initial_idx = cache->idx; - - if (initial_idx != uid) - { - return NULL; - } - - struct objc_slot *slot; - int32_t idx; - int32_t version; - do - { - initial_idx = cache->idx; - version = cache->version; - slot = cache->slot; - __sync_synchronize(); - idx = cache->idx; - } while (idx != initial_idx); - - return (idx == uid) && (slot->version == version) ? slot : NULL; -} - -static struct objc_slot *find_slot(uint32_t uid, - struct objc_slot **slots, int slot_count) -{ - if (slot_count == 0) { return NULL; } - int idx = slot_count >> 1; - struct objc_slot *slot = slots[idx]; - if (slot_count == 1) - { - if (slot->selector->index == uid) - { - return slot; - } - return NULL; - } - if (slot->selector->index > uid) - { - return find_slot(uid, slots, idx); - } - if (slot->selector->index < uid) - { - return find_slot(uid, slots+idx, slot_count - idx); - } - if (slot->selector->index == uid) - { - return slot; - } - return NULL; -} - -static int slot_cmp(const void *l, const void *r) -{ - return (*(struct objc_slot**)l)->selector->index - - (*(struct objc_slot**)r)->selector->index; -} - -static void insert_slot(dtable_t dtable, struct objc_slot *slot, uint32_t idx) -{ - if (dtable->slot_size == dtable->slot_count) - { - dtable->slot_size += 16; - dtable->slots = realloc(dtable->slots, dtable->slot_size * - sizeof(struct objc_slot)); - assert(NULL != dtable->slots && "Out of memory!"); - } - dtable->slots[dtable->slot_count++] = slot; -} - -static void add_slot_to_dtable(SEL sel, dtable_t dtable, uint32_t - old_slot_count, struct objc_method *m, Class cls) -{ - uint32_t idx = sel->index; - struct objc_slot *s = find_slot(idx, dtable->slots, old_slot_count); - if (NULL != s) - { - s->method = m->imp; - s->version++; - } - else - { - struct objc_slot *slot = new_slot_for_method_in_class(m, cls); - slot->selector = sel; - insert_slot(dtable, slot, idx); - if (Nil != cls->super_class) - { - slot = objc_dtable_lookup(dtable_for_class(cls->super_class), idx); - if (NULL != slot) - { - slot->version++; - } - } - } -} -static void update_dtable(dtable_t dtable) -{ - Class cls = dtable->cls; - - if (NULL == cls->methods) { return; } - - SparseArray *methods = SparseArrayNewWithDepth(dtable_depth); - collectMethodsForMethodListToSparseArray((void*)cls->methods, methods, YES); - - if (NULL == dtable->slots) - { - dtable->slots = calloc(sizeof(struct objc_slot), 16); - dtable->slot_size = 16; - } - - uint32_t old_slot_count = dtable->slot_count; - struct objc_method *m; - uint32_t idx = 0; - while ((m = SparseArrayNext(methods, &idx))) - { - add_slot_to_dtable(m->selector, dtable, old_slot_count, m, cls); -#ifdef TYPE_DEPENDENT_DISPATCH - add_slot_to_dtable(sel_getUntyped(m->selector), dtable, old_slot_count, m, cls); -#endif - } - mergesort(dtable->slots, dtable->slot_count, sizeof(struct objc_slot*), - slot_cmp); - SparseArrayDestroy(methods); -} - -PRIVATE void objc_update_dtable_for_class(Class cls) -{ - dtable_t dtable = dtable_for_class(cls); - // Be lazy about constructing the slot list - don't do it unless we actually - // need to access it - if ((NULL == dtable) || (NULL == dtable->slots)) { return; } - - LOCK_FOR_SCOPE(&dtable->lock); - - update_dtable(dtable); - -} -PRIVATE void add_method_list_to_class(Class cls, - struct objc_method_list *list) -{ - objc_update_dtable_for_class(cls); -} - -PRIVATE struct objc_slot* objc_dtable_lookup(dtable_t dtable, uint32_t uid) -{ - if (NULL == dtable) { return NULL; } - - struct objc_slot *slot = check_cache(dtable, uid); - - if (NULL != slot) - { - return slot; - } - - LOCK_FOR_SCOPE(&dtable->lock); - if (NULL == dtable->slots) - { - update_dtable(dtable); - } - slot = find_slot(uid, dtable->slots, dtable->slot_count); - if (NULL != slot) - { - int i = HASH_UID(uid); - volatile struct cache_line *cache = &dtable->cache[i]; - // Simplified multiword atomic exchange. First we write a value that - // is an invalid but recognisable UID and then a memory barrier. Then - // we complete the update and set the index pointer if and only if - // there have been no other modifications in the meantime - cache->idx = -uid; - __sync_synchronize(); - cache->version = slot->version; - cache->slot = slot; - __sync_bool_compare_and_swap(&cache->idx, -uid, uid); - return slot; - } - - if (NULL != dtable->cls->super_class) - { - return objc_dtable_lookup(dtable_for_class(dtable->cls->super_class), uid); - } - return NULL; -} -PRIVATE dtable_t objc_copy_dtable_for_class(dtable_t old, Class cls) -{ - dtable_t dtable = calloc(1, sizeof(struct objc_dtable)); - dtable->cls = cls; - INIT_LOCK(dtable->lock); - return dtable; -} - -PRIVATE void free_dtable(dtable_t dtable) -{ - if (NULL != dtable->slots) - { - free(dtable->slots); - } - DESTROY_LOCK(&dtable->lock); - free(dtable); -} - -#else - - PRIVATE void init_dispatch_tables () { INIT_LOCK(initialize_lock); @@ -750,8 +486,6 @@ PRIVATE void free_dtable(dtable_t dtable) SparseArrayDestroy(dtable); } -#endif // __OBJC_LOW_MEMORY__ - LEGACY void update_dispatch_table_for_class(Class cls) { static BOOL warned = NO;