Replaced GHashTable with HHashTable ... which has some problem causing it to segfault.

This commit is contained in:
Meredith L. Patterson 2012-10-08 21:12:56 +02:00
parent bc5e2fa754
commit b44d00ed33
3 changed files with 45 additions and 44 deletions

View file

@ -3,6 +3,7 @@
#include "allocator.h" #include "allocator.h"
#include <assert.h> #include <assert.h>
#include <malloc.h> #include <malloc.h>
#include <string.h>
// {{{ counted arrays // {{{ counted arrays
@ -97,14 +98,14 @@ void h_slist_free(HSlist *slist) {
h_arena_free(slist->arena, slist); h_arena_free(slist->arena, slist);
} }
HHashTable* h_hashtable_new(HArena *arena) { HHashTable* h_hashtable_new(HArena *arena, HEqualFunc equalFunc, HHashFunc hashFunc) {
HHashTable *ht = h_arena_malloc(arena, sizeof(HHashTable*)); HHashTable *ht = h_arena_malloc(arena, sizeof(HHashTable*));
ht->hashFunc = hashFunc; ht->hashFunc = hashFunc;
ht->equalFunc = equalFunc; ht->equalFunc = equalFunc;
ht->capacity = 64; // to start; should be tuned later... ht->capacity = 64; // to start; should be tuned later...
ht->used = 0; ht->used = 0;
ht->contents = h_arena_malloc(arena, sizeof(HHashTableEntry) * ht->capacity); ht->contents = h_arena_malloc(arena, sizeof(HHashTableEntry) * ht->capacity);
memset(ht->contents, sizeof(HHashTableEntry) * ht->capacity); memset(ht->contents, 0, sizeof(HHashTableEntry) * ht->capacity);
return ht; return ht;
} }
@ -127,14 +128,14 @@ void* h_hashtable_get(HHashTable* ht, void* key) {
void h_hashtable_put(HHashTable* ht, void* key, void* value) { void h_hashtable_put(HHashTable* ht, void* key, void* value) {
// # Start with a rebalancing // # Start with a rebalancing
h_hashtable_ensure_capacity(ht, ht->used + 1); //h_hashtable_ensure_capacity(ht, ht->used + 1);
HHashValue hashval = ht->hashFunc(key); HHashValue hashval = ht->hashFunc(key);
#ifdef CONSISTENCY_CHECK #ifdef CONSISTENCY_CHECK
assert((ht->capacity & (ht->capacity - 1)) == 0); // capacity is a power of 2 assert((ht->capacity & (ht->capacity - 1)) == 0); // capacity is a power of 2
#endif #endif
hte = &ht->contents[hashval & (ht->capacity - 1)]; HHashTableEntry *hte = &ht->contents[hashval & (ht->capacity - 1)];
if (hte->key != NULL) { if (hte->key != NULL) {
do { do {
if (hte->hashval == hashval && ht->equalFunc(key, hte->key)) if (hte->hashval == hashval && ht->equalFunc(key, hte->key))
@ -195,7 +196,7 @@ void h_hashtable_del(HHashTable* ht, void* key) {
} }
} }
void h_hashtable_free(HHashTable* ht) { void h_hashtable_free(HHashTable* ht) {
for (i = 0; i < ht->capacity; i++) { for (size_t i = 0; i < ht->capacity; i++) {
HHashTableEntry *hten, *hte = &ht->contents[i]; HHashTableEntry *hten, *hte = &ht->contents[i];
// FIXME: Free key and value // FIXME: Free key and value
hte = hte->next; hte = hte->next;

View file

@ -74,8 +74,8 @@ static inline HParseResult* perform_lowlevel_parse(HParseState *state, const HPa
} }
HParserCacheValue* recall(HParserCacheKey *k, HParseState *state) { HParserCacheValue* recall(HParserCacheKey *k, HParseState *state) {
HParserCacheValue *cached = g_hash_table_lookup(state->cache, k); HParserCacheValue *cached = h_hashtable_get(state->cache, k);
HRecursionHead *head = g_hash_table_lookup(state->recursion_heads, k); HRecursionHead *head = h_hashtable_get(state->recursion_heads, k);
if (!head) { // No heads found if (!head) { // No heads found
return cached; return cached;
} else { // Some heads found } else { // Some heads found
@ -126,8 +126,8 @@ void setupLR(const HParser *p, HParseState *state, HLeftRec *rec_detect) {
HParseResult* grow(HParserCacheKey *k, HParseState *state, HRecursionHead *head) { HParseResult* grow(HParserCacheKey *k, HParseState *state, HRecursionHead *head) {
// Store the head into the recursion_heads // Store the head into the recursion_heads
g_hash_table_replace(state->recursion_heads, k, head); h_hashtable_put(state->recursion_heads, k, head);
HParserCacheValue *old_cached = g_hash_table_lookup(state->cache, k); HParserCacheValue *old_cached = h_hashtable_get(state->cache, k);
if (!old_cached || PC_LEFT == old_cached->value_type) if (!old_cached || PC_LEFT == old_cached->value_type)
errx(1, "impossible match"); errx(1, "impossible match");
HParseResult *old_res = old_cached->right->result; HParseResult *old_res = old_cached->right->result;
@ -141,12 +141,12 @@ HParseResult* grow(HParserCacheKey *k, HParseState *state, HRecursionHead *head)
(old_res->ast->index == tmp_res->ast->index && old_res->ast->bit_offset < tmp_res->ast->bit_offset)) { (old_res->ast->index == tmp_res->ast->index && old_res->ast->bit_offset < tmp_res->ast->bit_offset)) {
HParserCacheValue *v = a_new(HParserCacheValue, 1); HParserCacheValue *v = a_new(HParserCacheValue, 1);
v->value_type = PC_RIGHT; v->right = cached_result(state, tmp_res); v->value_type = PC_RIGHT; v->right = cached_result(state, tmp_res);
g_hash_table_replace(state->cache, k, v); h_hashtable_put(state->cache, k, v);
return grow(k, state, head); return grow(k, state, head);
} else { } else {
// we're done with growing, we can remove data from the recursion head // we're done with growing, we can remove data from the recursion head
g_hash_table_remove(state->recursion_heads, k); h_hashtable_del(state->recursion_heads, k);
HParserCacheValue *cached = g_hash_table_lookup(state->cache, k); HParserCacheValue *cached = h_hashtable_get(state->cache, k);
if (cached && PC_RIGHT == cached->value_type) { if (cached && PC_RIGHT == cached->value_type) {
return cached->right->result; return cached->right->result;
} else { } else {
@ -154,7 +154,7 @@ HParseResult* grow(HParserCacheKey *k, HParseState *state, HRecursionHead *head)
} }
} }
} else { } else {
g_hash_table_remove(state->recursion_heads, k); h_hashtable_del(state->recursion_heads, k);
return old_res; return old_res;
} }
} }
@ -169,7 +169,7 @@ HParseResult* lr_answer(HParserCacheKey *k, HParseState *state, HLeftRec *growab
// update cache // update cache
HParserCacheValue *v = a_new(HParserCacheValue, 1); HParserCacheValue *v = a_new(HParserCacheValue, 1);
v->value_type = PC_RIGHT; v->right = cached_result(state, growable->seed); v->value_type = PC_RIGHT; v->right = cached_result(state, growable->seed);
g_hash_table_replace(state->cache, k, v); h_hashtable_put(state->cache, k, v);
if (!growable->seed) if (!growable->seed)
return NULL; return NULL;
else else
@ -194,7 +194,7 @@ HParseResult* h_do_parse(const HParser* parser, HParseState *state) {
// cache it // cache it
HParserCacheValue *dummy = a_new(HParserCacheValue, 1); HParserCacheValue *dummy = a_new(HParserCacheValue, 1);
dummy->value_type = PC_LEFT; dummy->left = base; dummy->value_type = PC_LEFT; dummy->left = base;
g_hash_table_replace(state->cache, key, dummy); h_hashtable_put(state->cache, key, dummy);
// parse the input // parse the input
HParseResult *tmp_res = perform_lowlevel_parse(state, parser); HParseResult *tmp_res = perform_lowlevel_parse(state, parser);
// the base variable has passed equality tests with the cache // the base variable has passed equality tests with the cache
@ -203,7 +203,7 @@ HParseResult* h_do_parse(const HParser* parser, HParseState *state) {
if (NULL == base->head) { if (NULL == base->head) {
HParserCacheValue *right = a_new(HParserCacheValue, 1); HParserCacheValue *right = a_new(HParserCacheValue, 1);
right->value_type = PC_RIGHT; right->right = cached_result(state, tmp_res); right->value_type = PC_RIGHT; right->right = cached_result(state, tmp_res);
g_hash_table_replace(state->cache, key, right); h_hashtable_put(state->cache, key, right);
return tmp_res; return tmp_res;
} else { } else {
base->seed = tmp_res; base->seed = tmp_res;
@ -242,8 +242,8 @@ HParseResult* h_parse(const HParser* parser, const uint8_t* input, size_t length
// Set up a parse state... // Set up a parse state...
HArena * arena = h_new_arena(0); HArena * arena = h_new_arena(0);
HParseState *parse_state = a_new_(arena, HParseState, 1); HParseState *parse_state = a_new_(arena, HParseState, 1);
parse_state->cache = g_hash_table_new(cache_key_hash, // hash_func parse_state->cache = h_hashtable_new(arena, cache_key_equal, // key_equal_func
cache_key_equal);// key_equal_func cache_key_hash); // hash_func
parse_state->input_stream.input = input; parse_state->input_stream.input = input;
parse_state->input_stream.index = 0; parse_state->input_stream.index = 0;
parse_state->input_stream.bit_offset = 8; // bit big endian parse_state->input_stream.bit_offset = 8; // bit big endian
@ -251,14 +251,14 @@ HParseResult* h_parse(const HParser* parser, const uint8_t* input, size_t length
parse_state->input_stream.endianness = BIT_BIG_ENDIAN | BYTE_BIG_ENDIAN; parse_state->input_stream.endianness = BIT_BIG_ENDIAN | BYTE_BIG_ENDIAN;
parse_state->input_stream.length = length; parse_state->input_stream.length = length;
parse_state->lr_stack = h_slist_new(arena); parse_state->lr_stack = h_slist_new(arena);
parse_state->recursion_heads = g_hash_table_new(cache_key_hash, parse_state->recursion_heads = h_hashtable_new(arena, cache_key_equal,
cache_key_equal); cache_key_hash);
parse_state->arena = arena; parse_state->arena = arena;
HParseResult *res = h_do_parse(parser, parse_state); HParseResult *res = h_do_parse(parser, parse_state);
h_slist_free(parse_state->lr_stack); h_slist_free(parse_state->lr_stack);
g_hash_table_destroy(parse_state->recursion_heads); h_hashtable_free(parse_state->recursion_heads);
// tear down the parse state // tear down the parse state
g_hash_table_destroy(parse_state->cache); h_hashtable_free(parse_state->cache);
if (!res) if (!res)
h_delete_arena(parse_state->arena); h_delete_arena(parse_state->arena);

View file

@ -52,6 +52,25 @@ typedef struct HSlist_ {
struct HArena_ *arena; struct HArena_ *arena;
} HSlist; } HSlist;
typedef unsigned int HHashValue;
typedef HHashValue (*HHashFunc)(const void* key);
typedef bool (*HEqualFunc)(const void* key1, const void* key2);
typedef struct HHashTableEntry_ {
struct HHashTableEntry_ *next;
void* key;
void* value;
HHashValue hashval;
} HHashTableEntry;
typedef struct HHashTable_ {
HHashTableEntry *contents;
HHashFunc hashFunc;
HEqualFunc equalFunc;
size_t capacity;
size_t used;
HArena *arena;
} HHashTable;
/* The state of the parser. /* The state of the parser.
* *
@ -65,11 +84,11 @@ typedef struct HSlist_ {
*/ */
struct HParseState_ { struct HParseState_ {
GHashTable *cache; HHashTable *cache;
HInputStream input_stream; HInputStream input_stream;
HArena * arena; HArena * arena;
HSlist *lr_stack; HSlist *lr_stack;
GHashTable *recursion_heads; HHashTable *recursion_heads;
}; };
/* The (location, parser) tuple used to key the cache. /* The (location, parser) tuple used to key the cache.
@ -172,26 +191,7 @@ bool h_slist_find(HSlist *slist, const void* item);
HSlist* h_slist_remove_all(HSlist *slist, const void* item); HSlist* h_slist_remove_all(HSlist *slist, const void* item);
void h_slist_free(HSlist *slist); void h_slist_free(HSlist *slist);
typedef unsigned int HHashValue; HHashTable* h_hashtable_new(HArena *arena, HEqualFunc equalFunc, HHashFunc hashFunc);
typedef HHashValue (*HHashFunc)(const void* key);
typedef bool (*HEqualFunc)(const void* key1, const void* key2);
typedef struct HHashTableEntry_ {
struct HHashTableEntry_ *next;
void* key;
void* value;
HHashValue hashval;
} HHashTableEntry;
typedef struct HHashTable_ {
HHashTableEntry *contents;
HHashFunc hashFunc;
HEqualFunc equalFunc;
int capacity;
int used;
} HHashTable;
HHashTable* h_hashtable_new(HArena *arena, );
void* h_hashtable_get(HHashTable* ht, void* key); void* h_hashtable_get(HHashTable* ht, void* key);
void h_hashtable_put(HHashTable* ht, void* key, void* value); void h_hashtable_put(HHashTable* ht, void* key, void* value);
int h_hashtable_present(HHashTable* ht, void* key); int h_hashtable_present(HHashTable* ht, void* key);