/home/mdboom/Work/builds/cpython/Python/ast_opt.c
Line | Count | Source (jump to first uncovered line) |
1 | /* AST Optimizer */ |
2 | #include "Python.h" |
3 | #include "pycore_ast.h" // _PyAST_GetDocString() |
4 | #include "pycore_compile.h" // _PyASTOptimizeState |
5 | #include "pycore_pystate.h" // _PyThreadState_GET() |
6 | #include "pycore_format.h" // F_LJUST |
7 | |
8 | |
9 | static int |
10 | make_const(expr_ty node, PyObject *val, PyArena *arena) |
11 | { |
12 | // Even if no new value was calculated, make_const may still |
13 | // need to clear an error (e.g. for division by zero) |
14 | if (val == NULL) { Branch (14:9): [True: 30.5k, False: 6.60k]
|
15 | if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) { Branch (15:13): [True: 0, False: 30.5k]
|
16 | return 0; |
17 | } |
18 | PyErr_Clear(); |
19 | return 1; |
20 | } |
21 | if (_PyArena_AddPyObject(arena, val) < 0) { Branch (21:9): [True: 0, False: 6.60k]
|
22 | Py_DECREF(val); |
23 | return 0; |
24 | } |
25 | node->kind = Constant_kind; |
26 | node->v.Constant.kind = NULL; |
27 | node->v.Constant.value = val; |
28 | return 1; |
29 | } |
30 | |
31 | #define COPY_NODE(TO, FROM) (memcpy((TO), (FROM), sizeof(struct _expr))) |
32 | |
33 | static int |
34 | has_starred(asdl_expr_seq *elts) |
35 | { |
36 | Py_ssize_t n = asdl_seq_LEN(elts); |
37 | for (Py_ssize_t i = 0; i < n; i++25.6k ) { Branch (37:28): [True: 25.6k, False: 24.1k]
|
38 | expr_ty e = (expr_ty)asdl_seq_GET(elts, i); |
39 | if (e->kind == Starred_kind) { Branch (39:13): [True: 5, False: 25.6k]
|
40 | return 1; |
41 | } |
42 | } |
43 | return 0; |
44 | } |
45 | |
46 | |
47 | static PyObject* |
48 | unary_not(PyObject *v) |
49 | { |
50 | int r = PyObject_IsTrue(v); |
51 | if (r < 0) Branch (51:9): [True: 0, False: 8]
|
52 | return NULL; |
53 | return PyBool_FromLong(!r); |
54 | } |
55 | |
56 | static int |
57 | fold_unaryop(expr_ty node, PyArena *arena, _PyASTOptimizeState *state) |
58 | { |
59 | expr_ty arg = node->v.UnaryOp.operand; |
60 | |
61 | if (arg->kind != Constant_kind) { Branch (61:9): [True: 4.61k, False: 3.09k]
|
62 | /* Fold not into comparison */ |
63 | if (node->v.UnaryOp.op == Not && arg->kind == Compare_kind4.22k && Branch (63:13): [True: 4.22k, False: 391]
Branch (63:42): [True: 125, False: 4.09k]
|
64 | asdl_seq_LEN125 (arg->v.Compare.ops) == 1125 ) { Branch (64:17): [True: 64, False: 61]
|
65 | /* Eq and NotEq are often implemented in terms of one another, so |
66 | folding not (self == other) into self != other breaks implementation |
67 | of !=. Detecting such cases doesn't seem worthwhile. |
68 | Python uses </> for 'is subset'/'is superset' operations on sets. |
69 | They don't satisfy not folding laws. */ |
70 | cmpop_ty op = asdl_seq_GET(arg->v.Compare.ops, 0); |
71 | switch (op) { Branch (71:21): [True: 0, False: 64]
|
72 | case Is: Branch (72:13): [True: 2, False: 62]
|
73 | op = IsNot; |
74 | break; |
75 | case IsNot: Branch (75:13): [True: 1, False: 63]
|
76 | op = Is; |
77 | break; |
78 | case In: Branch (78:13): [True: 35, False: 29]
|
79 | op = NotIn; |
80 | break; |
81 | case NotIn: Branch (81:13): [True: 1, False: 63]
|
82 | op = In; |
83 | break; |
84 | // The remaining comparison operators can't be safely inverted |
85 | case Eq: Branch (85:13): [True: 9, False: 55]
|
86 | case NotEq: Branch (86:13): [True: 1, False: 63]
|
87 | case Lt: Branch (87:13): [True: 3, False: 61]
|
88 | case LtE: Branch (88:13): [True: 4, False: 60]
|
89 | case Gt: Branch (89:13): [True: 7, False: 57]
|
90 | case GtE: Branch (90:13): [True: 1, False: 63]
|
91 | op = 0; // The AST enums leave "0" free as an "unused" marker |
92 | break; |
93 | // No default case, so the compiler will emit a warning if new |
94 | // comparison operators are added without being handled here |
95 | } |
96 | if (op) { Branch (96:17): [True: 39, False: 25]
|
97 | asdl_seq_SET(arg->v.Compare.ops, 0, op); |
98 | COPY_NODE(node, arg); |
99 | return 1; |
100 | } |
101 | } |
102 | return 1; |
103 | } |
104 | |
105 | typedef PyObject *(*unary_op)(PyObject*); |
106 | static const unary_op ops[] = { |
107 | [Invert] = PyNumber_Invert, |
108 | [Not] = unary_not, |
109 | [UAdd] = PyNumber_Positive, |
110 | [USub] = PyNumber_Negative, |
111 | }; |
112 | PyObject *newval = ops[node->v.UnaryOp.op](arg->v.Constant.value); |
113 | return make_const(node, newval, arena); |
114 | } |
115 | |
116 | /* Check whether a collection doesn't containing too much items (including |
117 | subcollections). This protects from creating a constant that needs |
118 | too much time for calculating a hash. |
119 | "limit" is the maximal number of items. |
120 | Returns the negative number if the total number of items exceeds the |
121 | limit. Otherwise returns the limit minus the total number of items. |
122 | */ |
123 | |
124 | static Py_ssize_t |
125 | check_complexity(PyObject *obj, Py_ssize_t limit) |
126 | { |
127 | if (PyTuple_Check(obj)) { |
128 | Py_ssize_t i; |
129 | limit -= PyTuple_GET_SIZE(obj); |
130 | for (i = 0; limit >= 0 && i < PyTuple_GET_SIZE(obj); i++11 ) { Branch (130:21): [True: 18, False: 0]
Branch (130:35): [True: 11, False: 7]
|
131 | limit = check_complexity(PyTuple_GET_ITEM(obj, i), limit); |
132 | } |
133 | return limit; |
134 | } |
135 | else if (PyFrozenSet_Check(obj)) { |
136 | Py_ssize_t i = 0; |
137 | PyObject *item; |
138 | Py_hash_t hash; |
139 | limit -= PySet_GET_SIZE(obj); |
140 | while (limit >= 0 && _PySet_NextEntry(obj, &i, &item, &hash)) { Branch (140:16): [True: 0, False: 0]
Branch (140:30): [True: 0, False: 0]
|
141 | limit = check_complexity(item, limit); |
142 | } |
143 | } |
144 | return limit; |
145 | } |
146 | |
147 | #define MAX_INT_SIZE 128 /* bits */ |
148 | #define MAX_COLLECTION_SIZE 256 /* items */ |
149 | #define MAX_STR_SIZE 4096 /* characters */ |
150 | #define MAX_TOTAL_ITEMS 1024 /* including nested collections */ |
151 | |
152 | static PyObject * |
153 | safe_multiply(PyObject *v, PyObject *w) |
154 | { |
155 | if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE47 (v) && Py_SIZE47 (w)) { |
156 | size_t vbits = _PyLong_NumBits(v); |
157 | size_t wbits = _PyLong_NumBits(w); |
158 | if (vbits == (size_t)-1 || wbits == (size_t)-1) { Branch (158:13): [True: 0, False: 47]
Branch (158:36): [True: 0, False: 47]
|
159 | return NULL; |
160 | } |
161 | if (vbits + wbits > MAX_INT_SIZE) { Branch (161:13): [True: 0, False: 47]
|
162 | return NULL; |
163 | } |
164 | } |
165 | else if (PyLong_Check(v) && (83 PyTuple_Check83 (w) || PyFrozenSet_Check76 (w))) { |
166 | Py_ssize_t size = PyTuple_Check(w) ? PyTuple_GET_SIZE(w) : |
167 | PySet_GET_SIZE0 (w); |
168 | if (size) { Branch (168:13): [True: 7, False: 0]
|
169 | long n = PyLong_AsLong(v); |
170 | if (n < 0 || n > MAX_COLLECTION_SIZE / size) { Branch (170:17): [True: 0, False: 7]
Branch (170:26): [True: 0, False: 7]
|
171 | return NULL; |
172 | } |
173 | if (n && check_complexity(w, MAX_TOTAL_ITEMS / n) < 0) { Branch (173:17): [True: 7, False: 0]
Branch (173:22): [True: 0, False: 7]
|
174 | return NULL; |
175 | } |
176 | } |
177 | } |
178 | else if (PyLong_Check(v) && (76 PyUnicode_Check76 (w) || PyBytes_Check76 (w))) { |
179 | Py_ssize_t size = PyUnicode_Check(w) ? PyUnicode_GET_LENGTH52 (w) : |
180 | PyBytes_GET_SIZE23 (w); |
181 | if (size) { Branch (181:13): [True: 75, False: 0]
|
182 | long n = PyLong_AsLong(v); |
183 | if (n < 0 || n > MAX_STR_SIZE / size) { Branch (183:17): [True: 0, False: 75]
Branch (183:26): [True: 29, False: 46]
|
184 | return NULL; |
185 | } |
186 | } |
187 | } |
188 | else if (PyLong_Check(w) && |
189 | (83 PyTuple_Check83 (v) || 83 PyFrozenSet_Check76 (v) || |
190 | PyUnicode_Check(v) || PyBytes_Check(v))) |
191 | { |
192 | return safe_multiply(w, v); |
193 | } |
194 | |
195 | return PyNumber_Multiply(v, w); |
196 | } |
197 | |
198 | static PyObject * |
199 | safe_power(PyObject *v, PyObject *w) |
200 | { |
201 | if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE55 (w) > 055 ) { Branch (201:61): [True: 55, False: 0]
|
202 | size_t vbits = _PyLong_NumBits(v); |
203 | size_t wbits = PyLong_AsSize_t(w); |
204 | if (vbits == (size_t)-1 || wbits == (size_t)-1) { Branch (204:13): [True: 0, False: 55]
Branch (204:36): [True: 0, False: 55]
|
205 | return NULL; |
206 | } |
207 | if (vbits > MAX_INT_SIZE / wbits) { Branch (207:13): [True: 6, False: 49]
|
208 | return NULL; |
209 | } |
210 | } |
211 | |
212 | return PyNumber_Power(v, w, Py_None); |
213 | } |
214 | |
215 | static PyObject * |
216 | safe_lshift(PyObject *v, PyObject *w) |
217 | { |
218 | if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w)) { |
219 | size_t vbits = _PyLong_NumBits(v); |
220 | size_t wbits = PyLong_AsSize_t(w); |
221 | if (vbits == (size_t)-1 || wbits == (size_t)-1) { Branch (221:13): [True: 0, False: 90]
Branch (221:36): [True: 0, False: 90]
|
222 | return NULL; |
223 | } |
224 | if (wbits > MAX_INT_SIZE || vbits > 88 MAX_INT_SIZE88 - wbits) { Branch (224:13): [True: 2, False: 88]
Branch (224:37): [True: 1, False: 87]
|
225 | return NULL; |
226 | } |
227 | } |
228 | |
229 | return PyNumber_Lshift(v, w); |
230 | } |
231 | |
232 | static PyObject * |
233 | safe_mod(PyObject *v, PyObject *w) |
234 | { |
235 | if (PyUnicode_Check(v) || PyBytes_Check3 (v)) { |
236 | return NULL; |
237 | } |
238 | |
239 | return PyNumber_Remainder(v, w); |
240 | } |
241 | |
242 | |
243 | static expr_ty |
244 | parse_literal(PyObject *fmt, Py_ssize_t *ppos, PyArena *arena) |
245 | { |
246 | const void *data = PyUnicode_DATA(fmt); |
247 | int kind = PyUnicode_KIND(fmt); |
248 | Py_ssize_t size = PyUnicode_GET_LENGTH(fmt); |
249 | Py_ssize_t start, pos; |
250 | int has_percents = 0; |
251 | start = pos = *ppos; |
252 | while (pos < size) { Branch (252:12): [True: 47.8k, False: 4.98k]
|
253 | if (PyUnicode_READ(kind, data, pos) != '%') { Branch (253:13): [True: 22.7k, False: 25.0k]
|
254 | pos++; |
255 | } |
256 | else if (pos+1 < size && PyUnicode_READ25.0k (kind, data, pos+1) == '%'25.0k ) { Branch (256:18): [True: 25.0k, False: 2]
Branch (256:34): [True: 7, False: 25.0k]
|
257 | has_percents = 1; |
258 | pos += 2; |
259 | } |
260 | else { |
261 | break; |
262 | } |
263 | } |
264 | *ppos = pos; |
265 | if (pos == start) { Branch (265:9): [True: 28.0k, False: 1.99k]
|
266 | return NULL; |
267 | } |
268 | PyObject *str = PyUnicode_Substring(fmt, start, pos); |
269 | /* str = str.replace('%%', '%') */ |
270 | if (str && has_percents) { Branch (270:9): [True: 1.99k, False: 0]
Branch (270:16): [True: 4, False: 1.99k]
|
271 | _Py_DECLARE_STR(percent, "%"); |
272 | _Py_DECLARE_STR(dbl_percent, "%%"); |
273 | Py_SETREF(str, PyUnicode_Replace(str, &_Py_STR(dbl_percent), |
274 | &_Py_STR(percent), -1)); |
275 | } |
276 | if (!str) { Branch (276:9): [True: 0, False: 1.99k]
|
277 | return NULL; |
278 | } |
279 | |
280 | if (_PyArena_AddPyObject(arena, str) < 0) { Branch (280:9): [True: 0, False: 1.99k]
|
281 | Py_DECREF(str); |
282 | return NULL; |
283 | } |
284 | return _PyAST_Constant(str, NULL, -1, -1, -1, -1, arena); |
285 | } |
286 | |
287 | #define MAXDIGITS 3 |
288 | |
289 | static int |
290 | simple_format_arg_parse(PyObject *fmt, Py_ssize_t *ppos, |
291 | int *spec, int *flags, int *width, int *prec) |
292 | { |
293 | Py_ssize_t pos = *ppos, len = PyUnicode_GET_LENGTH(fmt); |
294 | Py_UCS4 ch; |
295 | |
296 | #define NEXTC do { \ |
297 | if (pos >= len) { \ |
298 | return 0; \ |
299 | } \ |
300 | ch = 139k PyUnicode_READ_CHAR139k (fmt, pos); \ |
301 | pos++; \ |
302 | } while (0) |
303 | |
304 | *flags = 0; |
305 | while (1) { Branch (305:12): [Folded - Ignored]
|
306 | NEXTC; |
307 | switch (ch) { Branch (307:17): [True: 25.0k, False: 57.1k]
|
308 | case '-': *flags |= F_LJUST; continue; Branch (308:13): [True: 11.4k, False: 70.8k]
|
309 | case '+': *flags |= F_SIGN; continue; Branch (309:13): [True: 11.4k, False: 70.8k]
|
310 | case ' ': *flags |= F_BLANK; continue; Branch (310:13): [True: 11.4k, False: 70.8k]
|
311 | case '#': *flags |= F_ALT; continue; Branch (311:13): [True: 11.4k, False: 70.7k]
|
312 | case '0': *flags |= F_ZERO; continue; Branch (312:13): [True: 11.4k, False: 70.7k]
|
313 | case 'z': *flags |= F_NO_NEG_0; continue; Branch (313:13): [True: 1, False: 82.2k]
|
314 | } |
315 | break; |
316 | } |
317 | if ('0' <= ch && ch <= '9'18.5k ) { Branch (317:9): [True: 18.5k, False: 6.55k]
Branch (317:22): [True: 14.7k, False: 3.77k]
|
318 | *width = 0; |
319 | int digits = 0; |
320 | while ('0' <= ch && ch <= '9'26.2k ) { Branch (320:16): [True: 26.2k, False: 11.4k]
Branch (320:29): [True: 22.9k, False: 3.30k]
|
321 | *width = *width * 10 + (ch - '0'); |
322 | NEXTC; |
323 | if (++digits >= MAXDIGITS) { Branch (323:17): [True: 2, False: 22.9k]
|
324 | return 0; |
325 | } |
326 | } |
327 | } |
328 | |
329 | if (ch == '.') { Branch (329:9): [True: 17.9k, False: 7.10k]
|
330 | NEXTC; |
331 | *prec = 0; |
332 | if ('0' <= ch && ch <= '9'17.9k ) { Branch (332:13): [True: 17.9k, False: 1]
Branch (332:26): [True: 13.0k, False: 4.89k]
|
333 | int digits = 0; |
334 | while ('0' <= ch && ch <= '9') { Branch (334:20): [True: 29.3k, False: 0]
Branch (334:33): [True: 16.3k, False: 13.0k]
|
335 | *prec = *prec * 10 + (ch - '0'); |
336 | NEXTC; |
337 | if (++digits >= MAXDIGITS) { Branch (337:21): [True: 0, False: 16.3k]
|
338 | return 0; |
339 | } |
340 | } |
341 | } |
342 | } |
343 | *spec = ch; |
344 | *ppos = pos; |
345 | return 1; |
346 | |
347 | #undef NEXTC |
348 | } |
349 | |
350 | static expr_ty |
351 | parse_format(PyObject *fmt, Py_ssize_t *ppos, expr_ty arg, PyArena *arena) |
352 | { |
353 | int spec, flags, width = -1, prec = -1; |
354 | if (!simple_format_arg_parse(fmt, ppos, &spec, &flags, &width, &prec)) { Branch (354:9): [True: 3, False: 25.0k]
|
355 | // Unsupported format. |
356 | return NULL; |
357 | } |
358 | if (spec == 's' || spec == 'r'22.4k || spec == 'a'20.3k ) { Branch (358:9): [True: 2.63k, False: 22.4k]
Branch (358:24): [True: 2.04k, False: 20.3k]
Branch (358:39): [True: 1.34k, False: 19.0k]
|
359 | char buf[1 + MAXDIGITS + 1 + MAXDIGITS + 1], *p = buf; |
360 | if (!(flags & F_LJUST) && width > 03.99k ) { Branch (360:13): [True: 3.99k, False: 2.02k]
Branch (360:35): [True: 1.30k, False: 2.69k]
|
361 | *p++ = '>'; |
362 | } |
363 | if (width >= 0) { Branch (363:13): [True: 2.61k, False: 3.41k]
|
364 | p += snprintf(p, MAXDIGITS + 1, "%d", width); |
365 | } |
366 | if (prec >= 0) { Branch (366:13): [True: 3.16k, False: 2.85k]
|
367 | p += snprintf(p, MAXDIGITS + 2, ".%d", prec); |
368 | } |
369 | expr_ty format_spec = NULL; |
370 | if (p != buf) { Branch (370:13): [True: 3.76k, False: 2.25k]
|
371 | PyObject *str = PyUnicode_FromString(buf); |
372 | if (str == NULL) { Branch (372:17): [True: 0, False: 3.76k]
|
373 | return NULL; |
374 | } |
375 | if (_PyArena_AddPyObject(arena, str) < 0) { Branch (375:17): [True: 0, False: 3.76k]
|
376 | Py_DECREF(str); |
377 | return NULL; |
378 | } |
379 | format_spec = _PyAST_Constant(str, NULL, -1, -1, -1, -1, arena); |
380 | if (format_spec == NULL) { Branch (380:17): [True: 0, False: 3.76k]
|
381 | return NULL; |
382 | } |
383 | } |
384 | return _PyAST_FormattedValue(arg, spec, format_spec, |
385 | arg->lineno, arg->col_offset, |
386 | arg->end_lineno, arg->end_col_offset, |
387 | arena); |
388 | } |
389 | // Unsupported format. |
390 | return NULL; |
391 | } |
392 | |
393 | static int |
394 | optimize_format(expr_ty node, PyObject *fmt, asdl_expr_seq *elts, PyArena *arena) |
395 | { |
396 | Py_ssize_t pos = 0; |
397 | Py_ssize_t cnt = 0; |
398 | asdl_expr_seq *seq = _Py_asdl_expr_seq_new(asdl_seq_LEN(elts) * 2 + 1, arena); |
399 | if (!seq) { Branch (399:9): [True: 0, False: 24.0k]
|
400 | return 0; |
401 | } |
402 | seq->size = 0; |
403 | |
404 | while (1) { Branch (404:12): [Folded - Ignored]
|
405 | expr_ty lit = parse_literal(fmt, &pos, arena); |
406 | if (lit) { Branch (406:13): [True: 1.99k, False: 28.0k]
|
407 | asdl_seq_SET(seq, seq->size++, lit); |
408 | } |
409 | else if (PyErr_Occurred()) { Branch (409:18): [True: 0, False: 28.0k]
|
410 | return 0; |
411 | } |
412 | |
413 | if (pos >= PyUnicode_GET_LENGTH(fmt)) { Branch (413:13): [True: 4.98k, False: 25.0k]
|
414 | break; |
415 | } |
416 | if (cnt >= asdl_seq_LEN(elts)) { Branch (416:13): [True: 3, False: 25.0k]
|
417 | // More format units than items. |
418 | return 1; |
419 | } |
420 | assert(PyUnicode_READ_CHAR(fmt, pos) == '%'); |
421 | pos++; |
422 | expr_ty expr = parse_format(fmt, &pos, asdl_seq_GET(elts, cnt), arena); |
423 | cnt++; |
424 | if (!expr) { Branch (424:13): [True: 19.0k, False: 6.02k]
|
425 | return !PyErr_Occurred(); |
426 | } |
427 | asdl_seq_SET(seq, seq->size++, expr); |
428 | } |
429 | if (cnt < asdl_seq_LEN(elts)) { Branch (429:9): [True: 1, False: 4.98k]
|
430 | // More items than format units. |
431 | return 1; |
432 | } |
433 | expr_ty res = _PyAST_JoinedStr(seq, |
434 | node->lineno, node->col_offset, |
435 | node->end_lineno, node->end_col_offset, |
436 | arena); |
437 | if (!res) { Branch (437:9): [True: 0, False: 4.98k]
|
438 | return 0; |
439 | } |
440 | COPY_NODE(node, res); |
441 | // PySys_FormatStderr("format = %R\n", fmt); |
442 | return 1; |
443 | } |
444 | |
445 | static int |
446 | fold_binop(expr_ty node, PyArena *arena, _PyASTOptimizeState *state) |
447 | { |
448 | expr_ty lhs, rhs; |
449 | lhs = node->v.BinOp.left; |
450 | rhs = node->v.BinOp.right; |
451 | if (lhs->kind != Constant_kind) { Branch (451:9): [True: 42.0k, False: 27.1k]
|
452 | return 1; |
453 | } |
454 | PyObject *lv = lhs->v.Constant.value; |
455 | |
456 | if (node->v.BinOp.op == Mod && Branch (456:9): [True: 25.0k, False: 2.07k]
|
457 | rhs->kind == Tuple_kind25.0k && Branch (457:9): [True: 24.0k, False: 1.05k]
|
458 | PyUnicode_Check(lv) && |
459 | !has_starred(rhs->v.Tuple.elts)24.0k ) Branch (459:9): [True: 24.0k, False: 2]
|
460 | { |
461 | return optimize_format(node, lv, rhs->v.Tuple.elts, arena); |
462 | } |
463 | |
464 | if (rhs->kind != Constant_kind) { Branch (464:9): [True: 2.29k, False: 833]
|
465 | return 1; |
466 | } |
467 | |
468 | PyObject *rv = rhs->v.Constant.value; |
469 | PyObject *newval = NULL; |
470 | |
471 | switch (node->v.BinOp.op) { Branch (471:13): [True: 0, False: 833]
|
472 | case Add: Branch (472:5): [True: 286, False: 547]
|
473 | newval = PyNumber_Add(lv, rv); |
474 | break; |
475 | case Sub: Branch (475:5): [True: 134, False: 699]
|
476 | newval = PyNumber_Subtract(lv, rv); |
477 | break; |
478 | case Mult: Branch (478:5): [True: 133, False: 700]
|
479 | newval = safe_multiply(lv, rv); |
480 | break; |
481 | case Div: Branch (481:5): [True: 83, False: 750]
|
482 | newval = PyNumber_TrueDivide(lv, rv); |
483 | break; |
484 | case FloorDiv: Branch (484:5): [True: 22, False: 811]
|
485 | newval = PyNumber_FloorDivide(lv, rv); |
486 | break; |
487 | case Mod: Branch (487:5): [True: 8, False: 825]
|
488 | newval = safe_mod(lv, rv); |
489 | break; |
490 | case Pow: Branch (490:5): [True: 56, False: 777]
|
491 | newval = safe_power(lv, rv); |
492 | break; |
493 | case LShift: Branch (493:5): [True: 93, False: 740]
|
494 | newval = safe_lshift(lv, rv); |
495 | break; |
496 | case RShift: Branch (496:5): [True: 3, False: 830]
|
497 | newval = PyNumber_Rshift(lv, rv); |
498 | break; |
499 | case BitOr: Branch (499:5): [True: 7, False: 826]
|
500 | newval = PyNumber_Or(lv, rv); |
501 | break; |
502 | case BitXor: Branch (502:5): [True: 4, False: 829]
|
503 | newval = PyNumber_Xor(lv, rv); |
504 | break; |
505 | case BitAnd: Branch (505:5): [True: 4, False: 829]
|
506 | newval = PyNumber_And(lv, rv); |
507 | break; |
508 | // No builtin constants implement the following operators |
509 | case MatMult: Branch (509:5): [True: 0, False: 833]
|
510 | return 1; |
511 | // No default case, so the compiler will emit a warning if new binary |
512 | // operators are added without being handled here |
513 | } |
514 | |
515 | return make_const(node, newval, arena); |
516 | } |
517 | |
518 | static PyObject* |
519 | make_const_tuple(asdl_expr_seq *elts) |
520 | { |
521 | for (int i = 0; i < asdl_seq_LEN(elts); i++16.5k ) { Branch (521:21): [True: 46.9k, False: 2.76k]
|
522 | expr_ty e = (expr_ty)asdl_seq_GET(elts, i); |
523 | if (e->kind != Constant_kind) { Branch (523:13): [True: 30.3k, False: 16.5k]
|
524 | return NULL; |
525 | } |
526 | } |
527 | |
528 | PyObject *newval = PyTuple_New(asdl_seq_LEN(elts)); |
529 | if (newval == NULL) { Branch (529:9): [True: 0, False: 2.76k]
|
530 | return NULL; |
531 | } |
532 | |
533 | for (int i = 0; 2.76k i < asdl_seq_LEN(elts); i++15.9k ) { Branch (533:21): [True: 15.9k, False: 2.76k]
|
534 | expr_ty e = (expr_ty)asdl_seq_GET(elts, i); |
535 | PyObject *v = e->v.Constant.value; |
536 | Py_INCREF(v); |
537 | PyTuple_SET_ITEM(newval, i, v); |
538 | } |
539 | return newval; |
540 | } |
541 | |
542 | static int |
543 | fold_tuple(expr_ty node, PyArena *arena, _PyASTOptimizeState *state) |
544 | { |
545 | PyObject *newval; |
546 | |
547 | if (node->v.Tuple.ctx != Load) Branch (547:9): [True: 2.56k, False: 32.9k]
|
548 | return 1; |
549 | |
550 | newval = make_const_tuple(node->v.Tuple.elts); |
551 | return make_const(node, newval, arena); |
552 | } |
553 | |
554 | static int |
555 | fold_subscr(expr_ty node, PyArena *arena, _PyASTOptimizeState *state) |
556 | { |
557 | PyObject *newval; |
558 | expr_ty arg, idx; |
559 | |
560 | arg = node->v.Subscript.value; |
561 | idx = node->v.Subscript.slice; |
562 | if (node->v.Subscript.ctx != Load || Branch (562:9): [True: 2.81k, False: 12.1k]
|
563 | arg->kind != Constant_kind12.1k || Branch (563:13): [True: 12.1k, False: 32]
|
564 | idx->kind != Constant_kind32 ) Branch (564:13): [True: 20, False: 12]
|
565 | { |
566 | return 1; |
567 | } |
568 | |
569 | newval = PyObject_GetItem(arg->v.Constant.value, idx->v.Constant.value); |
570 | return make_const(node, newval, arena); |
571 | } |
572 | |
573 | /* Change literal list or set of constants into constant |
574 | tuple or frozenset respectively. Change literal list of |
575 | non-constants into tuple. |
576 | Used for right operand of "in" and "not in" tests and for iterable |
577 | in "for" loop and comprehensions. |
578 | */ |
579 | static int |
580 | fold_iter(expr_ty arg, PyArena *arena, _PyASTOptimizeState *state) |
581 | { |
582 | PyObject *newval; |
583 | if (arg->kind == List_kind) { Branch (583:9): [True: 119, False: 6.76k]
|
584 | /* First change a list into tuple. */ |
585 | asdl_expr_seq *elts = arg->v.List.elts; |
586 | if (has_starred(elts)) { Branch (586:13): [True: 3, False: 116]
|
587 | return 1; |
588 | } |
589 | expr_context_ty ctx = arg->v.List.ctx; |
590 | arg->kind = Tuple_kind; |
591 | arg->v.Tuple.elts = elts; |
592 | arg->v.Tuple.ctx = ctx; |
593 | /* Try to create a constant tuple. */ |
594 | newval = make_const_tuple(elts); |
595 | } |
596 | else if (arg->kind == Set_kind) { Branch (596:14): [True: 87, False: 6.67k]
|
597 | newval = make_const_tuple(arg->v.Set.elts); |
598 | if (newval) { Branch (598:13): [True: 72, False: 15]
|
599 | Py_SETREF(newval, PyFrozenSet_New(newval)); |
600 | } |
601 | } |
602 | else { |
603 | return 1; |
604 | } |
605 | return make_const(arg, newval, arena); |
606 | } |
607 | |
608 | static int |
609 | fold_compare(expr_ty node, PyArena *arena, _PyASTOptimizeState *state) |
610 | { |
611 | asdl_int_seq *ops; |
612 | asdl_expr_seq *args; |
613 | Py_ssize_t i; |
614 | |
615 | ops = node->v.Compare.ops; |
616 | args = node->v.Compare.comparators; |
617 | /* Change literal list or set in 'in' or 'not in' into |
618 | tuple or frozenset respectively. */ |
619 | i = asdl_seq_LEN(ops) - 1; |
620 | int op = asdl_seq_GET(ops, i); |
621 | if (op == In || op == NotIn15.6k ) { Branch (621:9): [True: 1.95k, False: 15.6k]
Branch (621:21): [True: 544, False: 15.1k]
|
622 | if (!fold_iter((expr_ty)asdl_seq_GET(args, i), arena, state)) { Branch (622:13): [True: 0, False: 2.50k]
|
623 | return 0; |
624 | } |
625 | } |
626 | return 1; |
627 | } |
628 | |
629 | static int astfold_mod(mod_ty node_, PyArena *ctx_, _PyASTOptimizeState *state); |
630 | static int astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state); |
631 | static int astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state); |
632 | static int astfold_arguments(arguments_ty node_, PyArena *ctx_, _PyASTOptimizeState *state); |
633 | static int astfold_comprehension(comprehension_ty node_, PyArena *ctx_, _PyASTOptimizeState *state); |
634 | static int astfold_keyword(keyword_ty node_, PyArena *ctx_, _PyASTOptimizeState *state); |
635 | static int astfold_arg(arg_ty node_, PyArena *ctx_, _PyASTOptimizeState *state); |
636 | static int astfold_withitem(withitem_ty node_, PyArena *ctx_, _PyASTOptimizeState *state); |
637 | static int astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, _PyASTOptimizeState *state); |
638 | static int astfold_match_case(match_case_ty node_, PyArena *ctx_, _PyASTOptimizeState *state); |
639 | static int astfold_pattern(pattern_ty node_, PyArena *ctx_, _PyASTOptimizeState *state); |
640 | |
641 | #define CALL(FUNC, TYPE, ARG) \ |
642 | if (!FUNC((ARG), ctx_, state)) \ |
643 | return 023.2k ; |
644 | |
645 | #define CALL_OPT(FUNC, TYPE, ARG) \ |
646 | if ((ARG) != NULL && !FUNC((ARG), ctx_, state)28.9k ) \ |
647 | return 00 ; |
648 | |
649 | #define CALL_SEQ(FUNC, TYPE, ARG) { \ |
650 | int i; \ |
651 | asdl_ ## TYPE ## _seq *seq = (ARG); /* avoid variable capture */ \ |
652 | for (i = 0; i < asdl_seq_LEN(seq); i++1.36M ) { \ |
653 | TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, i); \ |
654 | if (elt != NULL && !FUNC(elt, ctx_, state)1.36M ) \ |
655 | return 08 ; \ |
656 | } \ |
657 | } |
658 | |
659 | |
660 | static int |
661 | astfold_body(asdl_stmt_seq *stmts, PyArena *ctx_, _PyASTOptimizeState *state) |
662 | { |
663 | int docstring = _PyAST_GetDocString(stmts) != NULL; |
664 | CALL_SEQ(astfold_stmt, stmt, stmts); |
665 | if (!docstring && _PyAST_GetDocString(stmts) != NULL25.8k ) { Branch (665:9): [True: 25.8k, False: 5.80k]
Branch (665:23): [True: 0, False: 25.8k]
|
666 | stmt_ty st = (stmt_ty)asdl_seq_GET(stmts, 0); |
667 | asdl_expr_seq *values = _Py_asdl_expr_seq_new(1, ctx_); |
668 | if (!values) { Branch (668:13): [True: 0, False: 0]
|
669 | return 0; |
670 | } |
671 | asdl_seq_SET(values, 0, st->v.Expr.value); |
672 | expr_ty expr = _PyAST_JoinedStr(values, st->lineno, st->col_offset, |
673 | st->end_lineno, st->end_col_offset, |
674 | ctx_); |
675 | if (!expr) { Branch (675:13): [True: 0, False: 0]
|
676 | return 0; |
677 | } |
678 | st->v.Expr.value = expr; |
679 | } |
680 | return 1; |
681 | } |
682 | |
683 | static int |
684 | astfold_mod(mod_ty node_, PyArena *ctx_, _PyASTOptimizeState *state) |
685 | { |
686 | switch (node_->kind) { Branch (686:13): [True: 0, False: 49.0k]
|
687 | case Module_kind: Branch (687:5): [True: 9.01k, False: 40.0k]
|
688 | CALL(astfold_body, asdl_seq, node_->v.Module.body); |
689 | break; |
690 | case Interactive_kind: Branch (690:5): [True: 4.10k, False: 44.9k]
|
691 | CALL_SEQ(astfold_stmt, stmt, node_->v.Interactive.body); |
692 | break; |
693 | case Expression_kind: Branch (693:5): [True: 35.9k, False: 13.1k]
|
694 | CALL(astfold_expr, expr_ty, node_->v.Expression.body); |
695 | break; |
696 | // The following top level nodes don't participate in constant folding |
697 | case FunctionType_kind: Branch (697:5): [True: 0, False: 49.0k]
|
698 | break; |
699 | // No default case, so the compiler will emit a warning if new top level |
700 | // compilation nodes are added without being handled here |
701 | } |
702 | return 1; |
703 | } |
704 | |
705 | static int |
706 | astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state) |
707 | { |
708 | if (++state->recursion_depth > state->recursion_limit) { Branch (708:9): [True: 8, False: 1.76M]
|
709 | PyErr_SetString(PyExc_RecursionError, |
710 | "maximum recursion depth exceeded during compilation"); |
711 | return 0; |
712 | } |
713 | switch (node_->kind) { Branch (713:13): [True: 0, False: 1.76M]
|
714 | case BoolOp_kind: Branch (714:5): [True: 4.53k, False: 1.76M]
|
715 | CALL_SEQ(astfold_expr, expr, node_->v.BoolOp.values); |
716 | break; |
717 | case BinOp_kind: Branch (717:5): [True: 75.0k, False: 1.69M]
|
718 | CALL(astfold_expr, expr_ty, node_->v.BinOp.left); |
719 | CALL(astfold_expr, expr_ty, node_->v.BinOp.right); |
720 | CALL(fold_binop, expr_ty, node_); |
721 | break; |
722 | case UnaryOp_kind: Branch (722:5): [True: 7.70k, False: 1.76M]
|
723 | CALL(astfold_expr, expr_ty, node_->v.UnaryOp.operand); |
724 | CALL(fold_unaryop, expr_ty, node_); |
725 | break; |
726 | case Lambda_kind: Branch (726:5): [True: 880, False: 1.76M]
|
727 | CALL(astfold_arguments, arguments_ty, node_->v.Lambda.args); |
728 | CALL(astfold_expr, expr_ty, node_->v.Lambda.body); |
729 | break; |
730 | case IfExp_kind: Branch (730:5): [True: 568, False: 1.76M]
|
731 | CALL(astfold_expr, expr_ty, node_->v.IfExp.test); |
732 | CALL(astfold_expr, expr_ty, node_->v.IfExp.body); |
733 | CALL(astfold_expr, expr_ty, node_->v.IfExp.orelse); |
734 | break; |
735 | case Dict_kind: Branch (735:5): [True: 2.38k, False: 1.76M]
|
736 | CALL_SEQ(astfold_expr, expr, node_->v.Dict.keys); |
737 | CALL_SEQ(astfold_expr, expr, node_->v.Dict.values); |
738 | break; |
739 | case Set_kind: Branch (739:5): [True: 242, False: 1.76M]
|
740 | CALL_SEQ(astfold_expr, expr, node_->v.Set.elts); |
741 | break; |
742 | case ListComp_kind: Branch (742:5): [True: 651, False: 1.76M]
|
743 | CALL(astfold_expr, expr_ty, node_->v.ListComp.elt); |
744 | CALL_SEQ(astfold_comprehension, comprehension, node_->v.ListComp.generators); |
745 | break; |
746 | case SetComp_kind: Branch (746:5): [True: 123, False: 1.76M]
|
747 | CALL(astfold_expr, expr_ty, node_->v.SetComp.elt); |
748 | CALL_SEQ(astfold_comprehension, comprehension, node_->v.SetComp.generators); |
749 | break; |
750 | case DictComp_kind: Branch (750:5): [True: 63, False: 1.76M]
|
751 | CALL(astfold_expr, expr_ty, node_->v.DictComp.key); |
752 | CALL(astfold_expr, expr_ty, node_->v.DictComp.value); |
753 | CALL_SEQ(astfold_comprehension, comprehension, node_->v.DictComp.generators); |
754 | break; |
755 | case GeneratorExp_kind: Branch (755:5): [True: 509, False: 1.76M]
|
756 | CALL(astfold_expr, expr_ty, node_->v.GeneratorExp.elt); |
757 | CALL_SEQ(astfold_comprehension, comprehension, node_->v.GeneratorExp.generators); |
758 | break; |
759 | case Await_kind: Branch (759:5): [True: 85, False: 1.76M]
|
760 | CALL(astfold_expr, expr_ty, node_->v.Await.value); |
761 | break; |
762 | case Yield_kind: Branch (762:5): [True: 649, False: 1.76M]
|
763 | CALL_OPT(astfold_expr, expr_ty, node_->v.Yield.value); |
764 | break; |
765 | case YieldFrom_kind: Branch (765:5): [True: 115, False: 1.76M]
|
766 | CALL(astfold_expr, expr_ty, node_->v.YieldFrom.value); |
767 | break; |
768 | case Compare_kind: Branch (768:5): [True: 17.6k, False: 1.75M]
|
769 | CALL(astfold_expr, expr_ty, node_->v.Compare.left); |
770 | CALL_SEQ(astfold_expr, expr, node_->v.Compare.comparators); |
771 | CALL(fold_compare, expr_ty, node_); |
772 | break; |
773 | case Call_kind: Branch (773:5): [True: 72.8k, False: 1.69M]
|
774 | CALL(astfold_expr, expr_ty, node_->v.Call.func); |
775 | CALL_SEQ(astfold_expr, expr, node_->v.Call.args); |
776 | CALL_SEQ(astfold_keyword, keyword, node_->v.Call.keywords); |
777 | break; |
778 | case FormattedValue_kind: Branch (778:5): [True: 71.6k, False: 1.69M]
|
779 | CALL(astfold_expr, expr_ty, node_->v.FormattedValue.value); |
780 | CALL_OPT(astfold_expr, expr_ty, node_->v.FormattedValue.format_spec); |
781 | break; |
782 | case JoinedStr_kind: Branch (782:5): [True: 1.66k, False: 1.76M]
|
783 | CALL_SEQ(astfold_expr, expr, node_->v.JoinedStr.values); |
784 | break; |
785 | case Attribute_kind: Branch (785:5): [True: 78.9k, False: 1.68M]
|
786 | CALL(astfold_expr, expr_ty, node_->v.Attribute.value); |
787 | break; |
788 | case Subscript_kind: Branch (788:5): [True: 20.7k, False: 1.74M]
|
789 | CALL(astfold_expr, expr_ty, node_->v.Subscript.value); |
790 | CALL(astfold_expr, expr_ty, node_->v.Subscript.slice); |
791 | CALL(fold_subscr, expr_ty, node_); |
792 | break; |
793 | case Starred_kind: Branch (793:5): [True: 1.70k, False: 1.76M]
|
794 | CALL(astfold_expr, expr_ty, node_->v.Starred.value); |
795 | break; |
796 | case Slice_kind: Branch (796:5): [True: 2.00k, False: 1.76M]
|
797 | CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.lower); |
798 | CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.upper); |
799 | CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.step); |
800 | break; |
801 | case List_kind: Branch (801:5): [True: 4.02k, False: 1.76M]
|
802 | CALL_SEQ(astfold_expr, expr, node_->v.List.elts); |
803 | break; |
804 | case Tuple_kind: Branch (804:5): [True: 35.5k, False: 1.73M]
|
805 | CALL_SEQ(astfold_expr, expr, node_->v.Tuple.elts); |
806 | CALL(fold_tuple, expr_ty, node_); |
807 | break; |
808 | case Name_kind: Branch (808:5): [True: 822k, False: 944k]
|
809 | if (node_->v.Name.ctx == Load && Branch (809:13): [True: 761k, False: 61.8k]
|
810 | _PyUnicode_EqualToASCIIString(node_->v.Name.id, "__debug__")761k ) { Branch (810:17): [True: 42, False: 761k]
|
811 | state->recursion_depth--; |
812 | return make_const(node_, PyBool_FromLong(!state->optimize), ctx_); |
813 | } |
814 | break; |
815 | case NamedExpr_kind: Branch (815:5): [True: 307, False: 1.76M]
|
816 | CALL(astfold_expr, expr_ty, node_->v.NamedExpr.value); |
817 | break; |
818 | case Constant_kind: Branch (818:5): [True: 544k, False: 1.22M]
|
819 | // Already a constant, nothing further to do |
820 | break; |
821 | // No default case, so the compiler will emit a warning if new expression |
822 | // kinds are added without being handled here |
823 | } |
824 | state->recursion_depth--; |
825 | return 1; |
826 | } |
827 | |
828 | static int |
829 | astfold_keyword(keyword_ty node_, PyArena *ctx_, _PyASTOptimizeState *state) |
830 | { |
831 | CALL(astfold_expr, expr_ty, node_->value); |
832 | return 1; |
833 | } |
834 | |
835 | static int |
836 | astfold_comprehension(comprehension_ty node_, PyArena *ctx_, _PyASTOptimizeState *state) |
837 | { |
838 | CALL(astfold_expr, expr_ty, node_->target); |
839 | CALL(astfold_expr, expr_ty, node_->iter); |
840 | CALL_SEQ(astfold_expr, expr, node_->ifs); |
841 | |
842 | CALL(fold_iter, expr_ty, node_->iter); |
843 | return 1; |
844 | } |
845 | |
846 | static int |
847 | astfold_arguments(arguments_ty node_, PyArena *ctx_, _PyASTOptimizeState *state) |
848 | { |
849 | CALL_SEQ(astfold_arg, arg, node_->posonlyargs); |
850 | CALL_SEQ(astfold_arg, arg, node_->args); |
851 | CALL_OPT(astfold_arg, arg_ty, node_->vararg); |
852 | CALL_SEQ(astfold_arg, arg, node_->kwonlyargs); |
853 | CALL_SEQ(astfold_expr, expr, node_->kw_defaults); |
854 | CALL_OPT(astfold_arg, arg_ty, node_->kwarg); |
855 | CALL_SEQ(astfold_expr, expr, node_->defaults); |
856 | return 1; |
857 | } |
858 | |
859 | static int |
860 | astfold_arg(arg_ty node_, PyArena *ctx_, _PyASTOptimizeState *state) |
861 | { |
862 | if (!(state->ff_features & CO_FUTURE_ANNOTATIONS)) { Branch (862:9): [True: 44.3k, False: 348]
|
863 | CALL_OPT(astfold_expr, expr_ty, node_->annotation); |
864 | } |
865 | return 1; |
866 | } |
867 | |
868 | static int |
869 | astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state) |
870 | { |
871 | if (++state->recursion_depth > state->recursion_limit) { Branch (871:9): [True: 0, False: 568k]
|
872 | PyErr_SetString(PyExc_RecursionError, |
873 | "maximum recursion depth exceeded during compilation"); |
874 | return 0; |
875 | } |
876 | switch (node_->kind) { Branch (876:13): [True: 0, False: 568k]
|
877 | case FunctionDef_kind: Branch (877:5): [True: 20.4k, False: 547k]
|
878 | CALL(astfold_arguments, arguments_ty, node_->v.FunctionDef.args); |
879 | CALL(astfold_body, asdl_seq, node_->v.FunctionDef.body); |
880 | CALL_SEQ(astfold_expr, expr, node_->v.FunctionDef.decorator_list); |
881 | if (!(state->ff_features & CO_FUTURE_ANNOTATIONS)) { Branch (881:13): [True: 20.0k, False: 352]
|
882 | CALL_OPT(astfold_expr, expr_ty, node_->v.FunctionDef.returns); |
883 | } |
884 | break; |
885 | case AsyncFunctionDef_kind: Branch (885:5): [True: 471, False: 567k]
|
886 | CALL(astfold_arguments, arguments_ty, node_->v.AsyncFunctionDef.args); |
887 | CALL(astfold_body, asdl_seq, node_->v.AsyncFunctionDef.body); |
888 | CALL_SEQ(astfold_expr, expr, node_->v.AsyncFunctionDef.decorator_list); |
889 | if (!(state->ff_features & CO_FUTURE_ANNOTATIONS)) { Branch (889:13): [True: 126, False: 345]
|
890 | CALL_OPT(astfold_expr, expr_ty, node_->v.AsyncFunctionDef.returns); |
891 | } |
892 | break; |
893 | case ClassDef_kind: Branch (893:5): [True: 1.82k, False: 566k]
|
894 | CALL_SEQ(astfold_expr, expr, node_->v.ClassDef.bases); |
895 | CALL_SEQ(astfold_keyword, keyword, node_->v.ClassDef.keywords); |
896 | CALL(astfold_body, asdl_seq, node_->v.ClassDef.body); |
897 | CALL_SEQ(astfold_expr, expr, node_->v.ClassDef.decorator_list); |
898 | break; |
899 | case Return_kind: Branch (899:5): [True: 16.0k, False: 552k]
|
900 | CALL_OPT(astfold_expr, expr_ty, node_->v.Return.value); |
901 | break; |
902 | case Delete_kind: Branch (902:5): [True: 470, False: 567k]
|
903 | CALL_SEQ(astfold_expr, expr, node_->v.Delete.targets); |
904 | break; |
905 | case Assign_kind: Branch (905:5): [True: 55.0k, False: 513k]
|
906 | CALL_SEQ(astfold_expr, expr, node_->v.Assign.targets); |
907 | CALL(astfold_expr, expr_ty, node_->v.Assign.value); |
908 | break; |
909 | case AugAssign_kind: Branch (909:5): [True: 1.72k, False: 566k]
|
910 | CALL(astfold_expr, expr_ty, node_->v.AugAssign.target); |
911 | CALL(astfold_expr, expr_ty, node_->v.AugAssign.value); |
912 | break; |
913 | case AnnAssign_kind: Branch (913:5): [True: 952, False: 567k]
|
914 | CALL(astfold_expr, expr_ty, node_->v.AnnAssign.target); |
915 | if (!(state->ff_features & CO_FUTURE_ANNOTATIONS)) { Branch (915:13): [True: 84, False: 868]
|
916 | CALL(astfold_expr, expr_ty, node_->v.AnnAssign.annotation); |
917 | } |
918 | CALL_OPT(astfold_expr, expr_ty, node_->v.AnnAssign.value); |
919 | break; |
920 | case For_kind: Branch (920:5): [True: 2.92k, False: 565k]
|
921 | CALL(astfold_expr, expr_ty, node_->v.For.target); |
922 | CALL(astfold_expr, expr_ty, node_->v.For.iter); |
923 | CALL_SEQ(astfold_stmt, stmt, node_->v.For.body); |
924 | CALL_SEQ(astfold_stmt, stmt, node_->v.For.orelse); |
925 | |
926 | CALL(fold_iter, expr_ty, node_->v.For.iter); |
927 | break; |
928 | case AsyncFor_kind: Branch (928:5): [True: 36, False: 568k]
|
929 | CALL(astfold_expr, expr_ty, node_->v.AsyncFor.target); |
930 | CALL(astfold_expr, expr_ty, node_->v.AsyncFor.iter); |
931 | CALL_SEQ(astfold_stmt, stmt, node_->v.AsyncFor.body); |
932 | CALL_SEQ(astfold_stmt, stmt, node_->v.AsyncFor.orelse); |
933 | break; |
934 | case While_kind: Branch (934:5): [True: 807, False: 567k]
|
935 | CALL(astfold_expr, expr_ty, node_->v.While.test); |
936 | CALL_SEQ(astfold_stmt, stmt, node_->v.While.body); |
937 | CALL_SEQ(astfold_stmt, stmt, node_->v.While.orelse); |
938 | break; |
939 | case If_kind: Branch (939:5): [True: 220k, False: 347k]
|
940 | CALL(astfold_expr, expr_ty, node_->v.If.test); |
941 | CALL_SEQ(astfold_stmt, stmt, node_->v.If.body); |
942 | CALL_SEQ(astfold_stmt, stmt, node_->v.If.orelse); |
943 | break; |
944 | case With_kind: Branch (944:5): [True: 805, False: 567k]
|
945 | CALL_SEQ(astfold_withitem, withitem, node_->v.With.items); |
946 | CALL_SEQ(astfold_stmt, stmt, node_->v.With.body); |
947 | break; |
948 | case AsyncWith_kind: Branch (948:5): [True: 47, False: 568k]
|
949 | CALL_SEQ(astfold_withitem, withitem, node_->v.AsyncWith.items); |
950 | CALL_SEQ(astfold_stmt, stmt, node_->v.AsyncWith.body); |
951 | break; |
952 | case Raise_kind: Branch (952:5): [True: 4.12k, False: 564k]
|
953 | CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.exc); |
954 | CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.cause); |
955 | break; |
956 | case Try_kind: Branch (956:5): [True: 2.69k, False: 565k]
|
957 | CALL_SEQ(astfold_stmt, stmt, node_->v.Try.body); |
958 | CALL_SEQ(astfold_excepthandler, excepthandler, node_->v.Try.handlers); |
959 | CALL_SEQ(astfold_stmt, stmt, node_->v.Try.orelse); |
960 | CALL_SEQ(astfold_stmt, stmt, node_->v.Try.finalbody); |
961 | break; |
962 | case TryStar_kind: Branch (962:5): [True: 41, False: 568k]
|
963 | CALL_SEQ(astfold_stmt, stmt, node_->v.TryStar.body); |
964 | CALL_SEQ(astfold_excepthandler, excepthandler, node_->v.TryStar.handlers); |
965 | CALL_SEQ(astfold_stmt, stmt, node_->v.TryStar.orelse); |
966 | CALL_SEQ(astfold_stmt, stmt, node_->v.TryStar.finalbody); |
967 | break; |
968 | case Assert_kind: Branch (968:5): [True: 423, False: 567k]
|
969 | CALL(astfold_expr, expr_ty, node_->v.Assert.test); |
970 | CALL_OPT(astfold_expr, expr_ty, node_->v.Assert.msg); |
971 | break; |
972 | case Expr_kind: Branch (972:5): [True: 229k, False: 338k]
|
973 | CALL(astfold_expr, expr_ty, node_->v.Expr.value); |
974 | break; |
975 | case Match_kind: Branch (975:5): [True: 379, False: 568k]
|
976 | CALL(astfold_expr, expr_ty, node_->v.Match.subject); |
977 | CALL_SEQ(astfold_match_case, match_case, node_->v.Match.cases); |
978 | break; |
979 | // The following statements don't contain any subexpressions to be folded |
980 | case Import_kind: Branch (980:5): [True: 3.17k, False: 565k]
|
981 | case ImportFrom_kind: Branch (981:5): [True: 1.48k, False: 566k]
|
982 | case Global_kind: Branch (982:5): [True: 120, False: 568k]
|
983 | case Nonlocal_kind: Branch (983:5): [True: 71, False: 568k]
|
984 | case Pass_kind: Branch (984:5): [True: 2.35k, False: 566k]
|
985 | case Break_kind: Branch (985:5): [True: 796, False: 567k]
|
986 | case Continue_kind: Branch (986:5): [True: 568, False: 567k]
|
987 | break; |
988 | // No default case, so the compiler will emit a warning if new statement |
989 | // kinds are added without being handled here |
990 | } |
991 | state->recursion_depth--; |
992 | return 1; |
993 | } |
994 | |
995 | static int |
996 | astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, _PyASTOptimizeState *state) |
997 | { |
998 | switch (node_->kind) { Branch (998:13): [True: 0, False: 2.56k]
|
999 | case ExceptHandler_kind: Branch (999:5): [True: 2.56k, False: 0]
|
1000 | CALL_OPT(astfold_expr, expr_ty, node_->v.ExceptHandler.type); |
1001 | CALL_SEQ(astfold_stmt, stmt, node_->v.ExceptHandler.body); |
1002 | break; |
1003 | // No default case, so the compiler will emit a warning if new handler |
1004 | // kinds are added without being handled here |
1005 | } |
1006 | return 1; |
1007 | } |
1008 | |
1009 | static int |
1010 | astfold_withitem(withitem_ty node_, PyArena *ctx_, _PyASTOptimizeState *state) |
1011 | { |
1012 | CALL(astfold_expr, expr_ty, node_->context_expr); |
1013 | CALL_OPT(astfold_expr, expr_ty, node_->optional_vars); |
1014 | return 1; |
1015 | } |
1016 | |
1017 | static int |
1018 | astfold_pattern(pattern_ty node_, PyArena *ctx_, _PyASTOptimizeState *state) |
1019 | { |
1020 | // Currently, this is really only used to form complex/negative numeric |
1021 | // constants in MatchValue and MatchMapping nodes |
1022 | // We still recurse into all subexpressions and subpatterns anyway |
1023 | if (++state->recursion_depth > state->recursion_limit) { Branch (1023:9): [True: 0, False: 1.64k]
|
1024 | PyErr_SetString(PyExc_RecursionError, |
1025 | "maximum recursion depth exceeded during compilation"); |
1026 | return 0; |
1027 | } |
1028 | switch (node_->kind) { Branch (1028:13): [True: 0, False: 1.64k]
|
1029 | case MatchValue_kind: Branch (1029:9): [True: 389, False: 1.25k]
|
1030 | CALL(astfold_expr, expr_ty, node_->v.MatchValue.value); |
1031 | break; |
1032 | case MatchSingleton_kind: Branch (1032:9): [True: 16, False: 1.62k]
|
1033 | break; |
1034 | case MatchSequence_kind: Branch (1034:9): [True: 294, False: 1.34k]
|
1035 | CALL_SEQ(astfold_pattern, pattern, node_->v.MatchSequence.patterns); |
1036 | break; |
1037 | case MatchMapping_kind: Branch (1037:9): [True: 194, False: 1.44k]
|
1038 | CALL_SEQ(astfold_expr, expr, node_->v.MatchMapping.keys); |
1039 | CALL_SEQ(astfold_pattern, pattern, node_->v.MatchMapping.patterns); |
1040 | break; |
1041 | case MatchClass_kind: Branch (1041:9): [True: 92, False: 1.54k]
|
1042 | CALL(astfold_expr, expr_ty, node_->v.MatchClass.cls); |
1043 | CALL_SEQ(astfold_pattern, pattern, node_->v.MatchClass.patterns); |
1044 | CALL_SEQ(astfold_pattern, pattern, node_->v.MatchClass.kwd_patterns); |
1045 | break; |
1046 | case MatchStar_kind: Branch (1046:9): [True: 65, False: 1.57k]
|
1047 | break; |
1048 | case MatchAs_kind: Branch (1048:9): [True: 529, False: 1.11k]
|
1049 | if (node_->v.MatchAs.pattern) { Branch (1049:17): [True: 48, False: 481]
|
1050 | CALL(astfold_pattern, pattern_ty, node_->v.MatchAs.pattern); |
1051 | } |
1052 | break; |
1053 | case MatchOr_kind: Branch (1053:9): [True: 61, False: 1.57k]
|
1054 | CALL_SEQ(astfold_pattern, pattern, node_->v.MatchOr.patterns); |
1055 | break; |
1056 | // No default case, so the compiler will emit a warning if new pattern |
1057 | // kinds are added without being handled here |
1058 | } |
1059 | state->recursion_depth--; |
1060 | return 1; |
1061 | } |
1062 | |
1063 | static int |
1064 | astfold_match_case(match_case_ty node_, PyArena *ctx_, _PyASTOptimizeState *state) |
1065 | { |
1066 | CALL(astfold_pattern, expr_ty, node_->pattern); |
1067 | CALL_OPT(astfold_expr, expr_ty, node_->guard); |
1068 | CALL_SEQ(astfold_stmt, stmt, node_->body); |
1069 | return 1; |
1070 | } |
1071 | |
1072 | #undef CALL |
1073 | #undef CALL_OPT |
1074 | #undef CALL_SEQ |
1075 | |
1076 | /* See comments in symtable.c. */ |
1077 | #define COMPILER_STACK_FRAME_SCALE 3 |
1078 | |
1079 | int |
1080 | _PyAST_Optimize(mod_ty mod, PyArena *arena, _PyASTOptimizeState *state) |
1081 | { |
1082 | PyThreadState *tstate; |
1083 | int recursion_limit = Py_GetRecursionLimit(); |
1084 | int starting_recursion_depth; |
1085 | |
1086 | /* Setup recursion depth check counters */ |
1087 | tstate = _PyThreadState_GET(); |
1088 | if (!tstate) { Branch (1088:9): [True: 0, False: 49.0k]
|
1089 | return 0; |
1090 | } |
1091 | /* Be careful here to prevent overflow. */ |
1092 | int recursion_depth = tstate->recursion_limit - tstate->recursion_remaining; |
1093 | starting_recursion_depth = (recursion_depth < INT_MAX / COMPILER_STACK_FRAME_SCALE) ? Branch (1093:32): [True: 49.0k, False: 0]
|
1094 | recursion_depth * COMPILER_STACK_FRAME_SCALE : recursion_depth0 ; |
1095 | state->recursion_depth = starting_recursion_depth; |
1096 | state->recursion_limit = (recursion_limit < INT_MAX / COMPILER_STACK_FRAME_SCALE) ? Branch (1096:30): [True: 49.0k, False: 0]
|
1097 | recursion_limit * COMPILER_STACK_FRAME_SCALE : recursion_limit0 ; |
1098 | |
1099 | int ret = astfold_mod(mod, arena, state); |
1100 | assert(ret || PyErr_Occurred()); |
1101 | |
1102 | /* Check that the recursion depth counting balanced correctly */ |
1103 | if (ret && state->recursion_depth != starting_recursion_depth49.0k ) { Branch (1103:9): [True: 49.0k, False: 8]
Branch (1103:16): [True: 0, False: 49.0k]
|
1104 | PyErr_Format(PyExc_SystemError, |
1105 | "AST optimizer recursion depth mismatch (before=%d, after=%d)", |
1106 | starting_recursion_depth, state->recursion_depth); |
1107 | return 0; |
1108 | } |
1109 | |
1110 | return ret; |
1111 | } |