Skip to content

Commit d49e76b

Browse files
authored
gh-153568: Skip parser memo lookups that cannot match (#153571)
Each token now carries a small filter of the rule types present in its memo list, so the common case of a miss no longer walks the list.
1 parent 5763bfd commit d49e76b

3 files changed

Lines changed: 11 additions & 0 deletions

File tree

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Speed up the parser by letting memoization lookups that cannot match return
2+
immediately.

Parser/pegen.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ _PyPegen_insert_memo(Parser *p, int mark, int type, void *node)
100100
m->mark = p->mark;
101101
m->next = p->tokens[mark]->memo;
102102
p->tokens[mark]->memo = m;
103+
p->tokens[mark]->memo_mask |= 1ULL << (type & 63);
103104
return 0;
104105
}
105106

@@ -360,6 +361,10 @@ _PyPegen_is_memoized(Parser *p, int type, void *pres)
360361

361362
Token *t = p->tokens[p->mark];
362363

364+
if (!(t->memo_mask & (1ULL << (type & 63)))) {
365+
return 0;
366+
}
367+
363368
for (Memo *m = t->memo; m != NULL; m = m->next) {
364369
if (m->type == type) {
365370
#if defined(Py_DEBUG)

Parser/pegen.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ typedef struct {
4242
int level;
4343
int lineno, col_offset, end_lineno, end_col_offset;
4444
Memo *memo;
45+
// Filter over the rule types present in `memo` (bit `type & 63` is set
46+
// for every entry): lets lookups skip walking the list on definite
47+
// misses, which are the common case.
48+
uint64_t memo_mask;
4549
PyObject *metadata;
4650
} Token;
4751

0 commit comments

Comments
 (0)