diff -rpU3 save/regex_internal.h ./regex_internal.h --- save/regex_internal.h Wed Oct 23 09:56:46 2002 +++ ./regex_internal.h Wed Oct 23 10:17:36 2002 @@ -400,8 +400,8 @@ struct re_state_table_entry struct re_backref_cache_entry { - int node, dst_node; - int str_idx; + int node, str_idx, hash; + int dst_node; int subexp_from; int subexp_to; int subexp_len; @@ -425,6 +425,8 @@ typedef struct int abkref_ents; struct re_backref_cache_entry *bkref_ents; int max_mb_elem_len; + /* Cache the last lookup in the back reference cache. */ + int cache_node, cache_str_idx, cache_first_idx, cache_last_idx; } re_match_context_t; typedef struct diff -rpU3 save/regexec.c ./regexec.c --- save/regexec.c Wed Oct 23 09:56:46 2002 +++ ./regexec.c Wed Oct 23 10:16:49 2002 @@ -1901,7 +1901,7 @@ sift_states_bkref (preg, mctx, sctx, str { reg_errcode_t err; re_dfa_t *dfa = (re_dfa_t *)preg->buffer; - int node_idx, node; + int node_idx, node, hash; re_sift_context_t local_sctx; const re_node_set *candidates; candidates = ((mctx->state_log[str_idx] == NULL) ? &empty_set @@ -1920,15 +1920,50 @@ sift_states_bkref (preg, mctx, sctx, str continue; type = dfa->nodes[node].type; + hash = str_idx + (node << 16); if (type == OP_BACK_REF) { int enabled_idx; - for (enabled_idx = 0; enabled_idx < mctx->nbkref_ents; ++enabled_idx) + if (node == mctx->cache_node && str_idx == mctx->cache_str_idx) + enabled_idx = mctx->cache_first_idx; + else + { + for (enabled_idx = mctx->nbkref_ents; enabled_idx--; ) + { + struct re_backref_cache_entry *entry; + entry = mctx->bkref_ents + enabled_idx; + if (entry->hash == hash + && BE(entry->node == node, 1) + && BE(entry->str_idx == str_idx, 1)) + { + mctx->cache_node = node; + mctx->cache_str_idx = str_idx; + mctx->cache_last_idx = enabled_idx; + break; + } + } + for (enabled_idx = 0; enabled_idx <= mctx->cache_last_idx; ++enabled_idx) + { + struct re_backref_cache_entry *entry; + entry = mctx->bkref_ents + enabled_idx; + if (entry->hash == hash + && BE(entry->node == node, 1) + && BE(entry->str_idx == str_idx, 1)) + { + mctx->cache_first_idx = enabled_idx; + break; + } + } + } + + for (; enabled_idx <= mctx->cache_last_idx; ++enabled_idx) { int disabled_idx, subexp_len, to_idx, dst_node; struct re_backref_cache_entry *entry; entry = mctx->bkref_ents + enabled_idx; - if (entry->node != node || entry->str_idx != str_idx) + if (entry->hash != hash + || BE(entry->node != node, 0) + || BE(entry->str_idx != str_idx, 0)) continue; subexp_len = entry->subexp_len; @@ -1966,11 +2001,13 @@ sift_states_bkref (preg, mctx, sctx, str re_dfastate_t *cur_state; entry->flag = 0; for (disabled_idx = enabled_idx + 1; - disabled_idx < mctx->nbkref_ents; ++disabled_idx) + disabled_idx <= mctx->cache_last_idx; ++disabled_idx) { struct re_backref_cache_entry *entry2; entry2 = mctx->bkref_ents + disabled_idx; - if (entry2->node != node || entry2->str_idx != str_idx) + if (entry2->hash != hash + || BE(entry2->node != node, 0) + || BE(entry2->str_idx != str_idx, 0)) continue; entry2->flag = 1; } @@ -2007,11 +2044,14 @@ sift_states_bkref (preg, mctx, sctx, str mctx->bkref_ents[enabled_idx].flag = 1; } } - for (enabled_idx = 0; enabled_idx < mctx->nbkref_ents; ++enabled_idx) + for (enabled_idx = mctx->cache_first_idx; + enabled_idx <= mctx->cache_last_idx; ++enabled_idx) { struct re_backref_cache_entry *entry; entry = mctx->bkref_ents + enabled_idx; - if (entry->node == node && entry->str_idx == str_idx) + if (entry->hash == hash + && BE(entry->node == node, 1) + && BE(entry->str_idx == str_idx, 1)) entry->flag = 0; } } @@ -3109,6 +3149,11 @@ match_ctx_init (mctx, eflags, input, n) mctx->nbkref_ents = 0; mctx->abkref_ents = n; mctx->max_mb_elem_len = 0; + mctx->cache_node = -1; + mctx->cache_str_idx = -1; + mctx->cache_first_idx = 0; + mctx->cache_last_idx = 0; + return REG_NOERROR; } @@ -3138,8 +3183,13 @@ match_ctx_add_entry (mctx, dfa, node, st sizeof (struct re_backref_cache_entry) * mctx->abkref_ents); mctx->abkref_ents *= 2; } + + if (mctx->cache_node == node && mctx->cache_str_idx == str_idx) + mctx->cache_last_idx = mctx->nbkref_ents; + mctx->bkref_ents[mctx->nbkref_ents].node = node; mctx->bkref_ents[mctx->nbkref_ents].str_idx = str_idx; + mctx->bkref_ents[mctx->nbkref_ents].hash = str_idx + (node << 16); mctx->bkref_ents[mctx->nbkref_ents].subexp_from = from; mctx->bkref_ents[mctx->nbkref_ents].subexp_to = to; mctx->bkref_ents[mctx->nbkref_ents].subexp_len = to - from; @@ -3149,6 +3199,7 @@ match_ctx_add_entry (mctx, dfa, node, st mctx->bkref_ents[mctx->nbkref_ents++].flag = 0; if (mctx->max_mb_elem_len < to - from) mctx->max_mb_elem_len = to - from; + return REG_NOERROR; }