mirror of
https://github.com/JakeHillion/drgn.git
synced 2024-12-22 09:13:06 +00:00
libdrgn: hash_table: move entry_to_key to DEFINE_HASH_TABLE_FUNCTIONS()
DEFINE_HASH_TABLE_TYPE() doesn't actually need to know the key type. Move that argument (and some of the derived constants) to DEFINE_HASH_TABLE_FUNCTIONS(). This will allow recursive hash table types. As a nice side effect, it also reduces the size of common header files. Signed-off-by: Omar Sandoval <osandov@osandov.com>
This commit is contained in:
parent
802d6cc9ff
commit
1339dc6a2f
@ -480,6 +480,23 @@ err:
|
||||
|
||||
DEFINE_VECTOR_FUNCTIONS(drgn_debug_info_module_vector)
|
||||
|
||||
struct drgn_debug_info_module_key {
|
||||
const void *build_id;
|
||||
size_t build_id_len;
|
||||
uint64_t start, end;
|
||||
};
|
||||
|
||||
static inline struct drgn_debug_info_module_key
|
||||
drgn_debug_info_module_key(struct drgn_debug_info_module * const *entry)
|
||||
{
|
||||
return (struct drgn_debug_info_module_key){
|
||||
.build_id = (*entry)->build_id,
|
||||
.build_id_len = (*entry)->build_id_len,
|
||||
.start = (*entry)->start,
|
||||
.end = (*entry)->end,
|
||||
};
|
||||
}
|
||||
|
||||
static inline struct hash_pair
|
||||
drgn_debug_info_module_key_hash_pair(const struct drgn_debug_info_module_key *key)
|
||||
{
|
||||
@ -497,11 +514,11 @@ drgn_debug_info_module_key_eq(const struct drgn_debug_info_module_key *a,
|
||||
a->start == b->start && a->end == b->end);
|
||||
}
|
||||
DEFINE_HASH_TABLE_FUNCTIONS(drgn_debug_info_module_table,
|
||||
drgn_debug_info_module_key,
|
||||
drgn_debug_info_module_key_hash_pair,
|
||||
drgn_debug_info_module_key_eq)
|
||||
|
||||
DEFINE_HASH_TABLE_FUNCTIONS(c_string_set, c_string_key_hash_pair,
|
||||
c_string_key_eq)
|
||||
DEFINE_HASH_SET_FUNCTIONS(c_string_set, c_string_key_hash_pair, c_string_key_eq)
|
||||
|
||||
/**
|
||||
* @c Dwfl_Callbacks::find_elf() implementation.
|
||||
@ -2566,8 +2583,7 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
DEFINE_HASH_TABLE_FUNCTIONS(drgn_dwarf_type_map, ptr_key_hash_pair,
|
||||
scalar_key_eq)
|
||||
DEFINE_HASH_MAP_FUNCTIONS(drgn_dwarf_type_map, ptr_key_hash_pair, scalar_key_eq)
|
||||
|
||||
/**
|
||||
* Return whether a DWARF DIE is little-endian.
|
||||
|
@ -244,25 +244,8 @@ struct drgn_error *drgn_find_die_ancestors(Dwarf_Die *die, Dwarf_Die **dies_ret,
|
||||
size_t *length_ret)
|
||||
__attribute__((__nonnull__(2, 3)));
|
||||
|
||||
struct drgn_debug_info_module_key {
|
||||
const void *build_id;
|
||||
size_t build_id_len;
|
||||
uint64_t start, end;
|
||||
};
|
||||
|
||||
static inline struct drgn_debug_info_module_key
|
||||
drgn_debug_info_module_key(struct drgn_debug_info_module * const *entry)
|
||||
{
|
||||
return (struct drgn_debug_info_module_key){
|
||||
.build_id = (*entry)->build_id,
|
||||
.build_id_len = (*entry)->build_id_len,
|
||||
.start = (*entry)->start,
|
||||
.end = (*entry)->end,
|
||||
};
|
||||
}
|
||||
DEFINE_HASH_TABLE_TYPE(drgn_debug_info_module_table,
|
||||
struct drgn_debug_info_module *,
|
||||
drgn_debug_info_module_key)
|
||||
struct drgn_debug_info_module *)
|
||||
|
||||
DEFINE_HASH_SET_TYPE(c_string_set, const char *)
|
||||
|
||||
|
@ -185,10 +185,17 @@ struct drgn_dwarf_index_pending_die {
|
||||
|
||||
DEFINE_VECTOR_FUNCTIONS(drgn_dwarf_index_pending_die_vector)
|
||||
|
||||
DEFINE_HASH_TABLE_FUNCTIONS(drgn_dwarf_index_die_map, string_hash_pair,
|
||||
string_eq)
|
||||
DEFINE_HASH_MAP_FUNCTIONS(drgn_dwarf_index_die_map, string_hash_pair, string_eq)
|
||||
DEFINE_VECTOR_FUNCTIONS(drgn_dwarf_index_die_vector)
|
||||
|
||||
static inline uintptr_t
|
||||
drgn_dwarf_index_specification_to_key(const struct drgn_dwarf_index_specification *entry)
|
||||
{
|
||||
return entry->declaration;
|
||||
}
|
||||
|
||||
DEFINE_HASH_TABLE_FUNCTIONS(drgn_dwarf_index_specification_map,
|
||||
drgn_dwarf_index_specification_to_key,
|
||||
int_key_hash_pair, scalar_key_eq)
|
||||
|
||||
static inline size_t hash_pair_to_shard(struct hash_pair hp)
|
||||
|
@ -123,15 +123,8 @@ struct drgn_dwarf_index_specification {
|
||||
uintptr_t addr;
|
||||
};
|
||||
|
||||
static inline uintptr_t
|
||||
drgn_dwarf_index_specification_to_key(const struct drgn_dwarf_index_specification *entry)
|
||||
{
|
||||
return entry->declaration;
|
||||
}
|
||||
|
||||
DEFINE_HASH_TABLE_TYPE(drgn_dwarf_index_specification_map,
|
||||
struct drgn_dwarf_index_specification,
|
||||
drgn_dwarf_index_specification_to_key)
|
||||
struct drgn_dwarf_index_specification)
|
||||
|
||||
DEFINE_VECTOR_TYPE(drgn_dwarf_index_cu_vector, struct drgn_dwarf_index_cu)
|
||||
|
||||
|
@ -375,15 +375,8 @@ static inline unsigned int table##_chunk_occupied(struct table##_chunk *chunk) \
|
||||
*
|
||||
* @sa DEFINE_HASH_TABLE()
|
||||
*/
|
||||
#define DEFINE_HASH_TABLE_TYPE(table, entry_type, entry_to_key) \
|
||||
#define DEFINE_HASH_TABLE_TYPE(table, entry_type) \
|
||||
typedef typeof(entry_type) table##_entry_type; \
|
||||
typedef typeof(entry_to_key((table##_entry_type *)0)) table##_key_type; \
|
||||
\
|
||||
static inline table##_key_type \
|
||||
table##_entry_to_key(const table##_entry_type *entry) \
|
||||
{ \
|
||||
return entry_to_key(entry); \
|
||||
} \
|
||||
\
|
||||
enum { \
|
||||
/* \
|
||||
@ -395,6 +388,79 @@ enum { \
|
||||
table##_vector_policy = sizeof(table##_entry_type) >= 24, \
|
||||
}; \
|
||||
\
|
||||
struct table { \
|
||||
struct table##_chunk *chunks; \
|
||||
struct { \
|
||||
/* \
|
||||
* The vector storage policy stores 32-bit indices, so we only \
|
||||
* need 32-bit sizes. \
|
||||
*/ \
|
||||
uint32_t chunk_mask; \
|
||||
uint32_t size; \
|
||||
/* Allocated together with chunks. */ \
|
||||
table##_entry_type *entries; \
|
||||
} vector[table##_vector_policy]; \
|
||||
struct { \
|
||||
size_t chunk_mask; \
|
||||
size_t size; \
|
||||
uintptr_t first_packed; \
|
||||
} basic[!table##_vector_policy]; \
|
||||
};
|
||||
|
||||
/*
|
||||
* Common search function implementation returning an item iterator. This is
|
||||
* shared by key lookups and index lookups.
|
||||
*/
|
||||
#define HASH_TABLE_SEARCH_IMPL(table, func, key_type, item_to_key, eq_func) \
|
||||
static struct table##_iterator table##_##func(struct table *table, \
|
||||
const key_type *key, \
|
||||
struct hash_pair hp) \
|
||||
{ \
|
||||
const size_t delta = hash_table_probe_delta(hp); \
|
||||
size_t index = hp.first; \
|
||||
for (size_t tries = 0; tries <= table##_chunk_mask(table); tries++) { \
|
||||
struct table##_chunk *chunk = \
|
||||
&table->chunks[index & table##_chunk_mask(table)]; \
|
||||
if (sizeof(*chunk) > 64) \
|
||||
__builtin_prefetch(&chunk->items[8]); \
|
||||
unsigned int mask = table##_chunk_match(chunk, hp.second), i; \
|
||||
for_each_bit(i, mask) { \
|
||||
table##_item_type *item = &chunk->items[i]; \
|
||||
key_type item_key = item_to_key(table, item); \
|
||||
if (likely(eq_func(key, &item_key))) { \
|
||||
return (struct table##_iterator){ \
|
||||
.item = item, \
|
||||
.index = i, \
|
||||
}; \
|
||||
} \
|
||||
} \
|
||||
if (likely(chunk->outbound_overflow_count == 0)) \
|
||||
break; \
|
||||
index += delta; \
|
||||
} \
|
||||
return (struct table##_iterator){}; \
|
||||
}
|
||||
|
||||
#define HASH_TABLE_SEARCH_BY_INDEX_ITEM_TO_KEY(table, item) (*(item)->index)
|
||||
|
||||
/**
|
||||
* Define the functions for a hash table.
|
||||
*
|
||||
* The hash table type must have already been defined with @ref
|
||||
* DEFINE_HASH_TABLE_TYPE().
|
||||
*
|
||||
* Unless the type and function definitions must be in separate places, use @ref
|
||||
* DEFINE_HASH_TABLE() instead.
|
||||
*/
|
||||
#define DEFINE_HASH_TABLE_FUNCTIONS(table, entry_to_key, hash_func, eq_func) \
|
||||
typedef typeof(entry_to_key((table##_entry_type *)0)) table##_key_type; \
|
||||
\
|
||||
static inline table##_key_type \
|
||||
table##_entry_to_key(const table##_entry_type *entry) \
|
||||
{ \
|
||||
return entry_to_key(entry); \
|
||||
} \
|
||||
\
|
||||
/* \
|
||||
* Item stored in a chunk. \
|
||||
* \
|
||||
@ -489,73 +555,6 @@ struct table##_iterator { \
|
||||
}; \
|
||||
}; \
|
||||
\
|
||||
struct table { \
|
||||
struct table##_chunk *chunks; \
|
||||
struct { \
|
||||
/* \
|
||||
* The vector storage policy stores 32-bit indices, so we only \
|
||||
* need 32-bit sizes. \
|
||||
*/ \
|
||||
uint32_t chunk_mask; \
|
||||
uint32_t size; \
|
||||
/* Allocated together with chunks. */ \
|
||||
table##_entry_type *entries; \
|
||||
} vector[table##_vector_policy]; \
|
||||
struct { \
|
||||
size_t chunk_mask; \
|
||||
size_t size; \
|
||||
uintptr_t first_packed; \
|
||||
} basic[!table##_vector_policy]; \
|
||||
};
|
||||
|
||||
/*
|
||||
* Common search function implementation returning an item iterator. This is
|
||||
* shared by key lookups and index lookups.
|
||||
*/
|
||||
#define HASH_TABLE_SEARCH_IMPL(table, func, key_type, item_to_key, eq_func) \
|
||||
static struct table##_iterator table##_##func(struct table *table, \
|
||||
const key_type *key, \
|
||||
struct hash_pair hp) \
|
||||
{ \
|
||||
const size_t delta = hash_table_probe_delta(hp); \
|
||||
size_t index = hp.first; \
|
||||
for (size_t tries = 0; tries <= table##_chunk_mask(table); tries++) { \
|
||||
struct table##_chunk *chunk = \
|
||||
&table->chunks[index & table##_chunk_mask(table)]; \
|
||||
if (sizeof(*chunk) > 64) \
|
||||
__builtin_prefetch(&chunk->items[8]); \
|
||||
unsigned int mask = table##_chunk_match(chunk, hp.second), i; \
|
||||
for_each_bit(i, mask) { \
|
||||
table##_item_type *item = &chunk->items[i]; \
|
||||
key_type item_key = item_to_key(table, item); \
|
||||
if (likely(eq_func(key, &item_key))) { \
|
||||
return (struct table##_iterator){ \
|
||||
.item = item, \
|
||||
.index = i, \
|
||||
}; \
|
||||
} \
|
||||
} \
|
||||
if (likely(chunk->outbound_overflow_count == 0)) \
|
||||
break; \
|
||||
index += delta; \
|
||||
} \
|
||||
return (struct table##_iterator){}; \
|
||||
}
|
||||
|
||||
#define HASH_TABLE_SEARCH_BY_INDEX_ITEM_TO_KEY(table, item) (*(item)->index)
|
||||
|
||||
/**
|
||||
* Define the functions for a hash table.
|
||||
*
|
||||
* The hash table type must have already been defined with @ref
|
||||
* DEFINE_HASH_TABLE_TYPE().
|
||||
*
|
||||
* Unless the type and function definitions must be in separate places, use @ref
|
||||
* DEFINE_HASH_TABLE() instead.
|
||||
*
|
||||
* @sa DEFINE_HASH_TABLE()
|
||||
*/
|
||||
#define DEFINE_HASH_TABLE_FUNCTIONS(table, hash_func, eq_func) \
|
||||
static inline struct hash_pair table##_hash(const table##_key_type *key) \
|
||||
{ \
|
||||
return hash_func(key); \
|
||||
@ -1425,24 +1424,38 @@ static struct table##_iterator table##_next(struct table##_iterator it) \
|
||||
* *</tt> and returns a @c bool.
|
||||
*/
|
||||
#define DEFINE_HASH_TABLE(table, entry_type, entry_to_key, hash_func, eq_func) \
|
||||
DEFINE_HASH_TABLE_TYPE(table, entry_type, entry_to_key) \
|
||||
DEFINE_HASH_TABLE_FUNCTIONS(table, hash_func, eq_func)
|
||||
|
||||
#define HASH_MAP_ENTRY_TO_KEY(entry) ((entry)->key)
|
||||
DEFINE_HASH_TABLE_TYPE(table, entry_type) \
|
||||
DEFINE_HASH_TABLE_FUNCTIONS(table, entry_to_key, hash_func, eq_func)
|
||||
|
||||
/**
|
||||
* Define a hash map type without defining its functions.
|
||||
*
|
||||
* The functions are defined with @ref DEFINE_HASH_TABLE_FUNCTIONS().
|
||||
* The functions are defined with @ref DEFINE_HASH_MAP_FUNCTIONS().
|
||||
*
|
||||
* @sa DEFINE_HASH_MAP(), DEFINE_HASH_TABLE_TYPE()
|
||||
*/
|
||||
#define DEFINE_HASH_MAP_TYPE(table, key_type, value_type) \
|
||||
struct table##_entry { \
|
||||
typeof(key_type) key; \
|
||||
typeof(value_type) value; \
|
||||
}; \
|
||||
DEFINE_HASH_TABLE_TYPE(table, struct table##_entry, HASH_MAP_ENTRY_TO_KEY)
|
||||
#define DEFINE_HASH_MAP_TYPE(table, key_type, value_type) \
|
||||
struct table##_entry { \
|
||||
typeof(key_type) key; \
|
||||
typeof(value_type) value; \
|
||||
}; \
|
||||
DEFINE_HASH_TABLE_TYPE(table, struct table##_entry)
|
||||
|
||||
#define HASH_MAP_ENTRY_TO_KEY(entry) ((entry)->key)
|
||||
|
||||
/**
|
||||
* Define the functions for a hash map.
|
||||
*
|
||||
* The hash map type must have already been defined with @ref
|
||||
* DEFINE_HASH_MAP_TYPE().
|
||||
*
|
||||
* Unless the type and function definitions must be in separate places, use @ref
|
||||
* DEFINE_HASH_MAP() instead.
|
||||
*
|
||||
* @sa DEFINE_HASH_TABLE_FUNCTIONS
|
||||
*/
|
||||
#define DEFINE_HASH_MAP_FUNCTIONS(table, hash_func, eq_func) \
|
||||
DEFINE_HASH_TABLE_FUNCTIONS(table, HASH_MAP_ENTRY_TO_KEY, hash_func, eq_func)
|
||||
|
||||
/**
|
||||
* Define a hash map interface.
|
||||
@ -1466,19 +1479,32 @@ DEFINE_HASH_TABLE_TYPE(table, struct table##_entry, HASH_MAP_ENTRY_TO_KEY)
|
||||
*/
|
||||
#define DEFINE_HASH_MAP(table, key_type, value_type, hash_func, eq_func) \
|
||||
DEFINE_HASH_MAP_TYPE(table, key_type, value_type) \
|
||||
DEFINE_HASH_TABLE_FUNCTIONS(table, hash_func, eq_func)
|
||||
|
||||
#define HASH_SET_ENTRY_TO_KEY(entry) (*(entry))
|
||||
DEFINE_HASH_MAP_FUNCTIONS(table, hash_func, eq_func)
|
||||
|
||||
/**
|
||||
* Define a hash set type without defining its functions.
|
||||
*
|
||||
* The functions are defined with @ref DEFINE_HASH_TABLE_FUNCTIONS().
|
||||
* The functions are defined with @ref DEFINE_HASH_SET_FUNCTIONS().
|
||||
*
|
||||
* @sa DEFINE_HASH_SET(), DEFINE_HASH_TABLE_TYPE()
|
||||
*/
|
||||
#define DEFINE_HASH_SET_TYPE(table, key_type) \
|
||||
DEFINE_HASH_TABLE_TYPE(table, key_type, HASH_SET_ENTRY_TO_KEY)
|
||||
#define DEFINE_HASH_SET_TYPE DEFINE_HASH_TABLE_TYPE
|
||||
|
||||
#define HASH_SET_ENTRY_TO_KEY(entry) (*(entry))
|
||||
|
||||
/**
|
||||
* Define the functions for a hash set.
|
||||
*
|
||||
* The hash set type must have already been defined with @ref
|
||||
* DEFINE_HASH_SET_TYPE().
|
||||
*
|
||||
* Unless the type and function definitions must be in separate places, use @ref
|
||||
* DEFINE_HASH_SET() instead.
|
||||
*
|
||||
* @sa DEFINE_HASH_TABLE_FUNCTIONS
|
||||
*/
|
||||
#define DEFINE_HASH_SET_FUNCTIONS(table, hash_func, eq_func) \
|
||||
DEFINE_HASH_TABLE_FUNCTIONS(table, HASH_SET_ENTRY_TO_KEY, hash_func, eq_func)
|
||||
|
||||
/**
|
||||
* Define a hash set interface.
|
||||
@ -1494,7 +1520,7 @@ DEFINE_HASH_TABLE_FUNCTIONS(table, hash_func, eq_func)
|
||||
*/
|
||||
#define DEFINE_HASH_SET(table, key_type, hash_func, eq_func) \
|
||||
DEFINE_HASH_SET_TYPE(table, key_type) \
|
||||
DEFINE_HASH_TABLE_FUNCTIONS(table, hash_func, eq_func)
|
||||
DEFINE_HASH_SET_FUNCTIONS(table, hash_func, eq_func)
|
||||
|
||||
/**
|
||||
* Empty hash table initializer.
|
||||
|
@ -32,7 +32,7 @@
|
||||
#include "util.h"
|
||||
|
||||
DEFINE_VECTOR_FUNCTIONS(drgn_prstatus_vector)
|
||||
DEFINE_HASH_TABLE_FUNCTIONS(drgn_prstatus_map, int_key_hash_pair, scalar_key_eq)
|
||||
DEFINE_HASH_MAP_FUNCTIONS(drgn_prstatus_map, int_key_hash_pair, scalar_key_eq)
|
||||
|
||||
static Elf_Type note_header_type(GElf_Phdr *phdr)
|
||||
{
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include "../vector.h"
|
||||
#include "../util.h"
|
||||
|
||||
DEFINE_HASH_TABLE_FUNCTIONS(pyobjectp_set, ptr_key_hash_pair, scalar_key_eq)
|
||||
DEFINE_HASH_SET_FUNCTIONS(pyobjectp_set, ptr_key_hash_pair, scalar_key_eq)
|
||||
|
||||
int Program_hold_object(Program *prog, PyObject *obj)
|
||||
{
|
||||
|
@ -170,10 +170,10 @@ static bool drgn_member_key_eq(const struct drgn_member_key *a,
|
||||
(!a->name_len || memcmp(a->name, b->name, a->name_len) == 0));
|
||||
}
|
||||
|
||||
DEFINE_HASH_TABLE_FUNCTIONS(drgn_member_map, drgn_member_key_hash_pair,
|
||||
drgn_member_key_eq)
|
||||
DEFINE_HASH_MAP_FUNCTIONS(drgn_member_map, drgn_member_key_hash_pair,
|
||||
drgn_member_key_eq)
|
||||
|
||||
DEFINE_HASH_TABLE_FUNCTIONS(drgn_type_set, ptr_key_hash_pair, scalar_key_eq)
|
||||
DEFINE_HASH_SET_FUNCTIONS(drgn_type_set, ptr_key_hash_pair, scalar_key_eq)
|
||||
|
||||
LIBDRGN_PUBLIC struct drgn_error *
|
||||
drgn_member_object(struct drgn_type_member *member,
|
||||
@ -329,8 +329,8 @@ static bool drgn_type_dedupe_eq(struct drgn_type * const *entry_a,
|
||||
* We don't deduplicate types with members, parameters, template parameters, or
|
||||
* enumerators, so the hash and comparison functions ignore those.
|
||||
*/
|
||||
DEFINE_HASH_TABLE_FUNCTIONS(drgn_dedupe_type_set, drgn_type_dedupe_hash_pair,
|
||||
drgn_type_dedupe_eq)
|
||||
DEFINE_HASH_SET_FUNCTIONS(drgn_dedupe_type_set, drgn_type_dedupe_hash_pair,
|
||||
drgn_type_dedupe_eq)
|
||||
|
||||
DEFINE_VECTOR_FUNCTIONS(drgn_typep_vector)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user