Use a simple C array for the selector types list.

The sparse array is not a particularly good fit.  It allowed us to do a
few things without locking, but those things were not on the critical
path anyway and it added complexity and memory usage for little gain.

This removes the only non-dtable user of the sparse array, which should
mean that we're able to optimise the sparse array for that single use a
bit better.
main
David Chisnall 10 years ago
parent 8b1d4fbcc2
commit de8e5f26ee

@ -9,7 +9,6 @@
#include <assert.h> #include <assert.h>
#include <ctype.h> #include <ctype.h>
#include "lock.h" #include "lock.h"
#include "sarray2.h"
#include "objc/runtime.h" #include "objc/runtime.h"
#include "method_list.h" #include "method_list.h"
#include "class.h" #include "class.h"
@ -37,10 +36,14 @@
* array. * array.
*/ */
static uint32_t selector_count = 1; static uint32_t selector_count = 1;
/**
* Size of the buffer.
*/
static size_t table_size;
/** /**
* Mapping from selector numbers to selector names. * Mapping from selector numbers to selector names.
*/ */
PRIVATE SparseArray *selector_list = NULL; PRIVATE struct sel_type_list **selector_list = NULL;
#ifdef DEBUG_SELECTOR_TABLE #ifdef DEBUG_SELECTOR_TABLE
#define DEBUG_LOG(...) fprintf(stderr, __VA_ARGS__) #define DEBUG_LOG(...) fprintf(stderr, __VA_ARGS__)
@ -51,6 +54,27 @@ PRIVATE SparseArray *selector_list = NULL;
// Get the functions for string hashing // Get the functions for string hashing
#include "string_hash.h" #include "string_hash.h"
/**
* Lock protecting the selector table.
*/
mutex_t selector_table_lock;
static inline struct sel_type_list *selLookup_locked(uint32_t idx)
{
if (idx > selector_count)
{
return NULL;
}
return selector_list[idx];
}
static inline struct sel_type_list *selLookup(uint32_t idx)
{
LOCK_FOR_SCOPE(&selector_table_lock);
return selLookup_locked(idx);
}
PRIVATE inline BOOL isSelRegistered(SEL sel) PRIVATE inline BOOL isSelRegistered(SEL sel)
{ {
if ((uintptr_t)sel->name < (uintptr_t)selector_count) if ((uintptr_t)sel->name < (uintptr_t)selector_count)
@ -65,8 +89,7 @@ static const char *sel_getNameNonUnique(SEL sel)
const char *name = sel->name; const char *name = sel->name;
if (isSelRegistered(sel)) if (isSelRegistered(sel))
{ {
struct sel_type_list * list = struct sel_type_list * list = selLookup_locked(sel->index);
SparseArrayLookup(selector_list, sel->index);
name = (list == NULL) ? NULL : list->value; name = (list == NULL) ? NULL : list->value;
} }
if (NULL == name) if (NULL == name)
@ -226,16 +249,11 @@ static inline uint32_t hash_selector(const void *s)
*/ */
static selector_table *sel_table; static selector_table *sel_table;
/**
* Lock protecting the selector table.
*/
mutex_t selector_table_lock;
static int selector_name_copies; static int selector_name_copies;
PRIVATE void log_selector_memory_usage(void) PRIVATE void log_selector_memory_usage(void)
{ {
fprintf(stderr, "%d bytes in selector name list.\n", SparseArraySize(selector_list)); fprintf(stderr, "%lu bytes in selector name list.\n", (unsigned long)(table_size * sizeof(void*)));
fprintf(stderr, "%d bytes in selector names.\n", selector_name_copies); fprintf(stderr, "%d bytes in selector names.\n", selector_name_copies);
fprintf(stderr, "%d bytes (%d entries) in selector hash table.\n", (int)(sel_table->table_size * fprintf(stderr, "%d bytes (%d entries) in selector hash table.\n", (int)(sel_table->table_size *
sizeof(struct selector_table_cell_struct)), sel_table->table_size); sizeof(struct selector_table_cell_struct)), sel_table->table_size);
@ -257,7 +275,8 @@ void objc_resize_dtables(uint32_t);
*/ */
PRIVATE void init_selector_tables() PRIVATE void init_selector_tables()
{ {
selector_list = SparseArrayNew(); selector_list = calloc(sizeof(void*), 4096);
table_size = 4096;
INIT_LOCK(selector_table_lock); INIT_LOCK(selector_table_lock);
selector_initialize(&sel_table, 4096); selector_initialize(&sel_table, 4096);
} }
@ -276,7 +295,19 @@ static inline void add_selector_to_table(SEL aSel, int32_t uid, uint32_t idx)
typeList->value = aSel->name; typeList->value = aSel->name;
typeList->next = 0; typeList->next = 0;
// Store the name. // Store the name.
SparseArrayInsert(selector_list, idx, typeList); if (idx >= table_size)
{
table_size *= 2;
struct sel_type_list **newList = calloc(sizeof(struct sel_type_list*), table_size);
if (newList == NULL)
{
abort();
}
memcpy(newList, selector_list, sizeof(void*)*(table_size/2));
free(selector_list);
selector_list = newList;
}
selector_list[idx] = typeList;
// Store the selector. // Store the selector.
selector_insert(sel_table, aSel); selector_insert(sel_table, aSel);
// Set the selector's name to the uid. // Set the selector's name to the uid.
@ -321,8 +352,7 @@ static inline void register_selector_locked(SEL aSel)
// Add this set of types to the list. // Add this set of types to the list.
// This is quite horrible. Most selectors will only have one type // This is quite horrible. Most selectors will only have one type
// encoding, so we're wasting a lot of memory like this. // encoding, so we're wasting a lot of memory like this.
struct sel_type_list *typeListHead = struct sel_type_list *typeListHead = selLookup_locked(untyped->index);
SparseArrayLookup(selector_list, untyped->index);
struct sel_type_list *typeList = struct sel_type_list *typeList =
(struct sel_type_list *)selector_pool_alloc(); (struct sel_type_list *)selector_pool_alloc();
typeList->value = aSel->types; typeList->value = aSel->types;
@ -400,8 +430,7 @@ static SEL objc_register_selector_copy(SEL aSel, BOOL copyArgs)
PRIVATE uint32_t sel_nextTypeIndex(uint32_t untypedIdx, uint32_t idx) PRIVATE uint32_t sel_nextTypeIndex(uint32_t untypedIdx, uint32_t idx)
{ {
struct sel_type_list *list = struct sel_type_list *list = selLookup(untypedIdx);
SparseArrayLookup(selector_list, untypedIdx);
if (NULL == list) { return 0; } if (NULL == list) { return 0; }
@ -431,8 +460,7 @@ const char *sel_getName(SEL sel)
const char *name = sel->name; const char *name = sel->name;
if (isSelRegistered(sel)) if (isSelRegistered(sel))
{ {
struct sel_type_list * list = struct sel_type_list * list = selLookup(sel->index);
SparseArrayLookup(selector_list, sel->index);
name = (list == NULL) ? NULL : list->value; name = (list == NULL) ? NULL : list->value;
} }
else else
@ -498,8 +526,7 @@ unsigned sel_copyTypes_np(const char *selName, const char **types, unsigned coun
SEL untyped = selector_lookup(selName, 0); SEL untyped = selector_lookup(selName, 0);
if (untyped == NULL) { return 0; } if (untyped == NULL) { return 0; }
struct sel_type_list *l = struct sel_type_list *l = selLookup(untyped->index);
SparseArrayLookup(selector_list, (uint32_t)(uintptr_t)untyped->name);
// Skip the head, which just contains the name, not the types. // Skip the head, which just contains the name, not the types.
l = l->next; l = l->next;
@ -532,8 +559,7 @@ unsigned sel_copyTypedSelectors_np(const char *selName, SEL *const sels, unsigne
SEL untyped = selector_lookup(selName, 0); SEL untyped = selector_lookup(selName, 0);
if (untyped == NULL) { return 0; } if (untyped == NULL) { return 0; }
struct sel_type_list *l = struct sel_type_list *l = selLookup(untyped->index);
SparseArrayLookup(selector_list, (uint32_t)(uintptr_t)untyped->name);
// Skip the head, which just contains the name, not the types. // Skip the head, which just contains the name, not the types.
l = l->next; l = l->next;
@ -599,8 +625,7 @@ SEL sel_get_typed_uid (const char *name, const char *types)
SEL sel = selector_lookup(name, types); SEL sel = selector_lookup(name, types);
if (NULL == sel) { return sel_registerTypedName_np(name, types); } if (NULL == sel) { return sel_registerTypedName_np(name, types); }
struct sel_type_list *l = struct sel_type_list *l = selLookup(sel->index);
SparseArrayLookup(selector_list, (uint32_t)(uintptr_t)sel->name);
// Skip the head, which just contains the name, not the types. // Skip the head, which just contains the name, not the types.
l = l->next; l = l->next;
if (NULL != l) if (NULL != l)
@ -616,8 +641,7 @@ SEL sel_get_any_typed_uid (const char *name)
SEL sel = selector_lookup(name, 0); SEL sel = selector_lookup(name, 0);
if (NULL == sel) { return sel_registerName(name); } if (NULL == sel) { return sel_registerName(name); }
struct sel_type_list *l = struct sel_type_list *l = selLookup(sel->index);
SparseArrayLookup(selector_list, (uint32_t)(uintptr_t)sel->name);
// Skip the head, which just contains the name, not the types. // Skip the head, which just contains the name, not the types.
l = l->next; l = l->next;
if (NULL != l) if (NULL != l)

Loading…
Cancel
Save