/src/Python-3.8.3/Parser/acceler.c
Line | Count | Source (jump to first uncovered line) |
1 | | |
2 | | /* Parser accelerator module */ |
3 | | |
4 | | /* The parser as originally conceived had disappointing performance. |
5 | | This module does some precomputation that speeds up the selection |
6 | | of a DFA based upon a token, turning a search through an array |
7 | | into a simple indexing operation. The parser now cannot work |
8 | | without the accelerators installed. Note that the accelerators |
9 | | are installed dynamically when the parser is initialized, they |
10 | | are not part of the static data structure written on graminit.[ch] |
11 | | by the parser generator. */ |
12 | | |
13 | | #include "Python.h" |
14 | | #include "grammar.h" |
15 | | #include "node.h" |
16 | | #include "token.h" |
17 | | #include "parser.h" |
18 | | |
19 | | /* Forward references */ |
20 | | static void fixdfa(grammar *, const dfa *); |
21 | | static void fixstate(grammar *, state *); |
22 | | |
23 | | void |
24 | | PyGrammar_AddAccelerators(grammar *g) |
25 | 14 | { |
26 | 14 | int i; |
27 | 14 | const dfa *d = g->g_dfa; |
28 | 1.30k | for (i = g->g_ndfas; --i >= 0; d++) |
29 | 1.28k | fixdfa(g, d); |
30 | 14 | g->g_accel = 1; |
31 | 14 | } |
32 | | |
33 | | void |
34 | | PyGrammar_RemoveAccelerators(grammar *g) |
35 | 0 | { |
36 | 0 | int i; |
37 | 0 | g->g_accel = 0; |
38 | 0 | const dfa *d = g->g_dfa; |
39 | 0 | for (i = g->g_ndfas; --i >= 0; d++) { |
40 | 0 | state *s; |
41 | 0 | int j; |
42 | 0 | s = d->d_state; |
43 | 0 | for (j = 0; j < d->d_nstates; j++, s++) { |
44 | 0 | if (s->s_accel) |
45 | 0 | PyObject_FREE(s->s_accel); |
46 | 0 | s->s_accel = NULL; |
47 | 0 | } |
48 | 0 | } |
49 | 0 | } |
50 | | |
51 | | static void |
52 | | fixdfa(grammar *g, const dfa *d) |
53 | 1.28k | { |
54 | 1.28k | state *s; |
55 | 1.28k | int j; |
56 | 1.28k | s = d->d_state; |
57 | 7.50k | for (j = 0; j < d->d_nstates; j++, s++) |
58 | 6.21k | fixstate(g, s); |
59 | 1.28k | } |
60 | | |
61 | | static void |
62 | | fixstate(grammar *g, state *s) |
63 | 6.21k | { |
64 | 6.21k | const arc *a; |
65 | 6.21k | int k; |
66 | 6.21k | int *accel; |
67 | 6.21k | int nl = g->g_ll.ll_nlabels; |
68 | 6.21k | s->s_accept = 0; |
69 | 6.21k | accel = (int *) PyObject_MALLOC(nl * sizeof(int)); |
70 | 6.21k | if (accel == NULL) { |
71 | 0 | fprintf(stderr, "no mem to build parser accelerators\n"); |
72 | 0 | exit(1); |
73 | 0 | } |
74 | 1.14M | for (k = 0; k < nl; k++) |
75 | 1.13M | accel[k] = -1; |
76 | 6.21k | a = s->s_arc; |
77 | 17.4k | for (k = s->s_narcs; --k >= 0; a++) { |
78 | 11.2k | int lbl = a->a_lbl; |
79 | 11.2k | const label *l = &g->g_ll.ll_label[lbl]; |
80 | 11.2k | int type = l->lb_type; |
81 | 11.2k | if (a->a_arrow >= (1 << 7)) { |
82 | 0 | printf("XXX too many states!\n"); |
83 | 0 | continue; |
84 | 0 | } |
85 | 11.2k | if (ISNONTERMINAL(type)) { |
86 | 3.51k | const dfa *d1 = PyGrammar_FindDFA(g, type); |
87 | 3.51k | int ibit; |
88 | 3.51k | if (type - NT_OFFSET >= (1 << 7)) { |
89 | 0 | printf("XXX too high nonterminal number!\n"); |
90 | 0 | continue; |
91 | 0 | } |
92 | 646k | for (ibit = 0; ibit < g->g_ll.ll_nlabels; ibit++) { |
93 | 643k | if (testbit(d1->d_first, ibit)) { |
94 | 37.7k | if (accel[ibit] != -1) |
95 | 0 | printf("XXX ambiguity!\n"); |
96 | 37.7k | accel[ibit] = a->a_arrow | (1 << 7) | |
97 | 37.7k | ((type - NT_OFFSET) << 8); |
98 | 37.7k | } |
99 | 643k | } |
100 | 3.51k | } |
101 | 7.74k | else if (lbl == EMPTY) |
102 | 2.82k | s->s_accept = 1; |
103 | 4.91k | else if (lbl >= 0 && lbl < nl) |
104 | 4.91k | accel[lbl] = a->a_arrow; |
105 | 11.2k | } |
106 | 839k | while (nl > 0 && accel[nl-1] == -1) |
107 | 833k | nl--; |
108 | 180k | for (k = 0; k < nl && accel[k] == -1;) |
109 | 173k | k++; |
110 | 6.21k | if (k < nl) { |
111 | 5.22k | int i; |
112 | 5.22k | s->s_accel = (int *) PyObject_MALLOC((nl-k) * sizeof(int)); |
113 | 5.22k | if (s->s_accel == NULL) { |
114 | 0 | fprintf(stderr, "no mem to add parser accelerators\n"); |
115 | 0 | exit(1); |
116 | 0 | } |
117 | 5.22k | s->s_lower = k; |
118 | 5.22k | s->s_upper = nl; |
119 | 135k | for (i = 0; k < nl; i++, k++) |
120 | 130k | s->s_accel[i] = accel[k]; |
121 | 5.22k | } |
122 | 6.21k | PyObject_FREE(accel); |
123 | 6.21k | } |