Merge branch 'fix-cache-hit-skip'

This commit is contained in:
Sven M. Hallberg 2012-06-02 02:52:22 +02:00
commit 12e296fc9a
2 changed files with 25 additions and 16 deletions

View file

@ -34,6 +34,15 @@ static guint djbhash(const uint8_t *buf, size_t len) {
return hash; return hash;
} }
// short-hand for constructing HCachedResult's
static HCachedResult *cached_result(const HParseState *state, HParseResult *result)
{
HCachedResult *ret = a_new(HCachedResult, 1);
ret->result = result;
ret->input_stream = state->input_stream;
return ret;
}
HParserCacheValue* recall(HParserCacheKey *k, HParseState *state) { HParserCacheValue* recall(HParserCacheKey *k, HParseState *state) {
HParserCacheValue *cached = g_hash_table_lookup(state->cache, k); HParserCacheValue *cached = g_hash_table_lookup(state->cache, k);
HRecursionHead *head = g_hash_table_lookup(state->recursion_heads, k); HRecursionHead *head = g_hash_table_lookup(state->recursion_heads, k);
@ -45,7 +54,7 @@ HParserCacheValue* recall(HParserCacheKey *k, HParseState *state) {
HParseResult *tmp = a_new(HParseResult, 1); HParseResult *tmp = a_new(HParseResult, 1);
tmp->ast = NULL; tmp->arena = state->arena; tmp->ast = NULL; tmp->arena = state->arena;
HParserCacheValue *ret = a_new(HParserCacheValue, 1); HParserCacheValue *ret = a_new(HParserCacheValue, 1);
ret->value_type = PC_RIGHT; ret->right = tmp; ret->value_type = PC_RIGHT; ret->right = cached_result(state, tmp);
return ret; return ret;
} }
if (g_slist_find(head->eval_set, k->parser)) { if (g_slist_find(head->eval_set, k->parser)) {
@ -58,7 +67,7 @@ HParserCacheValue* recall(HParserCacheKey *k, HParseState *state) {
if (!cached) if (!cached)
cached = a_new(HParserCacheValue, 1); cached = a_new(HParserCacheValue, 1);
cached->value_type = PC_RIGHT; cached->value_type = PC_RIGHT;
cached->right = tmp_res; cached->right = cached_result(state, tmp_res);
} }
return cached; return cached;
} }
@ -93,7 +102,7 @@ HParseResult* grow(HParserCacheKey *k, HParseState *state, HRecursionHead *head)
HParserCacheValue *old_cached = g_hash_table_lookup(state->cache, k); HParserCacheValue *old_cached = g_hash_table_lookup(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; HParseResult *old_res = old_cached->right->result;
// reset the eval_set of the head of the recursion at each beginning of growth // reset the eval_set of the head of the recursion at each beginning of growth
head->eval_set = head->involved_set; head->eval_set = head->involved_set;
@ -108,7 +117,7 @@ HParseResult* grow(HParserCacheKey *k, HParseState *state, HRecursionHead *head)
if ((old_res->ast->index < tmp_res->ast->index) || if ((old_res->ast->index < tmp_res->ast->index) ||
(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 = tmp_res; v->value_type = PC_RIGHT; v->right = cached_result(state, tmp_res);
g_hash_table_replace(state->cache, k, v); g_hash_table_replace(state->cache, k, v);
return grow(k, state, head); return grow(k, state, head);
} else { } else {
@ -116,7 +125,7 @@ HParseResult* grow(HParserCacheKey *k, HParseState *state, HRecursionHead *head)
g_hash_table_remove(state->recursion_heads, k); g_hash_table_remove(state->recursion_heads, k);
HParserCacheValue *cached = g_hash_table_lookup(state->cache, k); HParserCacheValue *cached = g_hash_table_lookup(state->cache, k);
if (cached && PC_RIGHT == cached->value_type) { if (cached && PC_RIGHT == cached->value_type) {
return cached->right; return cached->right->result;
} else { } else {
errx(1, "impossible match"); errx(1, "impossible match");
} }
@ -136,7 +145,7 @@ HParseResult* lr_answer(HParserCacheKey *k, HParseState *state, HLeftRec *growab
else { else {
// update cache // update cache
HParserCacheValue *v = a_new(HParserCacheValue, 1); HParserCacheValue *v = a_new(HParserCacheValue, 1);
v->value_type = PC_RIGHT; v->right = growable->seed; v->value_type = PC_RIGHT; v->right = cached_result(state, growable->seed);
g_hash_table_replace(state->cache, k, v); g_hash_table_replace(state->cache, k, v);
if (!growable->seed) if (!growable->seed)
return NULL; return NULL;
@ -194,7 +203,7 @@ HParseResult* h_do_parse(const HParser* parser, HParseState *state) {
// setupLR, used below, mutates the LR to have a head if appropriate, so we check to see if we have one // setupLR, used below, mutates the LR to have a head if appropriate, so we check to see if we have one
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 = tmp_res; right->value_type = PC_RIGHT; right->right = cached_result(state, tmp_res);
g_hash_table_replace(state->cache, key, right); g_hash_table_replace(state->cache, key, right);
return tmp_res; return tmp_res;
} else { } else {
@ -208,14 +217,8 @@ HParseResult* h_do_parse(const HParser* parser, HParseState *state) {
setupLR(parser, state, m->left); setupLR(parser, state, m->left);
return m->left->seed; // BUG: this might not be correct return m->left->seed; // BUG: this might not be correct
} else { } else {
HParseResult *res = m->right; state->input_stream = m->right->input_stream;
return m->right->result;
// skip over the previously-parsed input
long long offs = res->bit_length + state->input_stream.bit_offset;
state->input_stream.index += offs >> 3;
state->input_stream.bit_offset = offs & 7;
return res;
} }
} }
} }

View file

@ -108,6 +108,12 @@ typedef struct HLeftRec_ {
HRecursionHead *head; HRecursionHead *head;
} HLeftRec; } HLeftRec;
/* Result and remaining input, for rerunning from a cached position. */
typedef struct HCachedResult_ {
HParseResult *result;
HInputStream input_stream;
} HCachedResult;
/* Tagged union for values in the cache: either HLeftRec's (Left) or /* Tagged union for values in the cache: either HLeftRec's (Left) or
* HParseResult's (Right). * HParseResult's (Right).
*/ */
@ -115,7 +121,7 @@ typedef struct HParserCacheValue_t {
HParserCacheValueType value_type; HParserCacheValueType value_type;
union { union {
HLeftRec *left; HLeftRec *left;
HParseResult *right; HCachedResult *right;
}; };
} HParserCacheValue; } HParserCacheValue;