blob: 8789e01e9b848c34303edd9cf21e15c56a052a1c [file] [log] [blame]
Vladimir Marangozov58e64a82000-09-03 23:47:08 +00001/* Parse tree node implementation */
2
Tim Peters1d6a7292000-09-26 06:11:54 +00003#include "Python.h"
Vladimir Marangozov58e64a82000-09-03 23:47:08 +00004#include "node.h"
5#include "errcode.h"
6
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00007node *
Thomas Wouters23c9e002000-07-22 19:20:54 +00008PyNode_New(int type)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00009{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000010 node *n = (node *) PyObject_MALLOC(1 * sizeof(node));
11 if (n == NULL)
12 return NULL;
13 n->n_type = type;
14 n->n_str = NULL;
15 n->n_lineno = 0;
Ivan Levkivskyi9932a222019-01-22 11:18:22 +000016 n->n_end_lineno = 0;
Joannah Nanjekyed10091a2020-05-08 17:58:28 -030017 n->n_col_offset = 0;
Ivan Levkivskyi9932a222019-01-22 11:18:22 +000018 n->n_end_col_offset = -1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000019 n->n_nchildren = 0;
20 n->n_child = NULL;
21 return n;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000022}
23
Tim Peters623fdb92002-07-08 19:11:07 +000024/* See comments at XXXROUNDUP below. Returns -1 on overflow. */
Tim Peters755ebea2002-07-08 06:32:09 +000025static int
26fancy_roundup(int n)
27{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000028 /* Round up to the closest power of 2 >= n. */
29 int result = 256;
30 assert(n > 128);
31 while (result < n) {
32 result <<= 1;
33 if (result <= 0)
34 return -1;
35 }
36 return result;
Tim Peters755ebea2002-07-08 06:32:09 +000037}
38
39/* A gimmick to make massive numbers of reallocs quicker. The result is
Tim Peterse561dc22002-07-15 17:58:03 +000040 * a number >= the input. In PyNode_AddChild, it's used like so, when
41 * we're about to add child number current_size + 1:
42 *
43 * if XXXROUNDUP(current_size) < XXXROUNDUP(current_size + 1):
44 * allocate space for XXXROUNDUP(current_size + 1) total children
45 * else:
46 * we already have enough space
47 *
48 * Since a node starts out empty, we must have
49 *
50 * XXXROUNDUP(0) < XXXROUNDUP(1)
51 *
52 * so that we allocate space for the first child. One-child nodes are very
53 * common (presumably that would change if we used a more abstract form
54 * of syntax tree), so to avoid wasting memory it's desirable that
55 * XXXROUNDUP(1) == 1. That in turn forces XXXROUNDUP(0) == 0.
56 *
57 * Else for 2 <= n <= 128, we round up to the closest multiple of 4. Why 4?
58 * Rounding up to a multiple of an exact power of 2 is very efficient, and
59 * most nodes with more than one child have <= 4 kids.
60 *
61 * Else we call fancy_roundup() to grow proportionately to n. We've got an
Tim Peters755ebea2002-07-08 06:32:09 +000062 * extreme case then (like test_longexp.py), and on many platforms doing
63 * anything less than proportional growth leads to exorbitant runtime
64 * (e.g., MacPython), or extreme fragmentation of user address space (e.g.,
65 * Win98).
Tim Peterse561dc22002-07-15 17:58:03 +000066 *
67 * In a run of compileall across the 2.3a0 Lib directory, Andrew MacIntyre
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000068 * reported that, with this scheme, 89% of PyObject_REALLOC calls in
Tim Peterse561dc22002-07-15 17:58:03 +000069 * PyNode_AddChild passed 1 for the size, and 9% passed 4. So this usually
70 * wastes very little memory, but is very effective at sidestepping
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000071 * platform-realloc disasters on vulnerable platforms.
Tim Peterse561dc22002-07-15 17:58:03 +000072 *
73 * Note that this would be straightforward if a node stored its current
74 * capacity. The code is tricky to avoid that.
Tim Peters755ebea2002-07-08 06:32:09 +000075 */
Serhiy Storchaka67c719b2014-09-05 10:10:23 +030076#define XXXROUNDUP(n) ((n) <= 1 ? (n) : \
77 (n) <= 128 ? (int)_Py_SIZE_ROUND_UP((n), 4) : \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000078 fancy_roundup(n))
Tim Peters755ebea2002-07-08 06:32:09 +000079
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000080
Ivan Levkivskyi9932a222019-01-22 11:18:22 +000081void
82_PyNode_FinalizeEndPos(node *n)
83{
84 int nch = NCH(n);
85 node *last;
86 if (nch == 0) {
87 return;
88 }
89 last = CHILD(n, nch - 1);
90 _PyNode_FinalizeEndPos(last);
91 n->n_end_lineno = last->n_end_lineno;
92 n->n_end_col_offset = last->n_end_col_offset;
93}
94
Jeremy Hylton94988062000-06-20 19:10:44 +000095int
Ivan Levkivskyi9932a222019-01-22 11:18:22 +000096PyNode_AddChild(node *n1, int type, char *str, int lineno, int col_offset,
97 int end_lineno, int end_col_offset)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000098{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000099 const int nch = n1->n_nchildren;
100 int current_capacity;
101 int required_capacity;
102 node *n;
Tim Peters755ebea2002-07-08 06:32:09 +0000103
Ivan Levkivskyi9932a222019-01-22 11:18:22 +0000104 // finalize end position of previous node (if any)
105 if (nch > 0) {
106 _PyNode_FinalizeEndPos(CHILD(n1, nch - 1));
107 }
108
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000109 if (nch == INT_MAX || nch < 0)
110 return E_OVERFLOW;
Tim Peters755ebea2002-07-08 06:32:09 +0000111
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000112 current_capacity = XXXROUNDUP(nch);
113 required_capacity = XXXROUNDUP(nch + 1);
114 if (current_capacity < 0 || required_capacity < 0)
115 return E_OVERFLOW;
116 if (current_capacity < required_capacity) {
Benjamin Peterson2f8bfef2016-09-07 09:26:18 -0700117 if ((size_t)required_capacity > SIZE_MAX / sizeof(node)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000118 return E_NOMEM;
119 }
120 n = n1->n_child;
121 n = (node *) PyObject_REALLOC(n,
122 required_capacity * sizeof(node));
123 if (n == NULL)
124 return E_NOMEM;
125 n1->n_child = n;
126 }
Tim Peters755ebea2002-07-08 06:32:09 +0000127
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000128 n = &n1->n_child[n1->n_nchildren++];
129 n->n_type = type;
130 n->n_str = str;
131 n->n_lineno = lineno;
132 n->n_col_offset = col_offset;
Ivan Levkivskyi9932a222019-01-22 11:18:22 +0000133 n->n_end_lineno = end_lineno; // this and below will be updates after all children are added.
134 n->n_end_col_offset = end_col_offset;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000135 n->n_nchildren = 0;
136 n->n_child = NULL;
137 return 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000138}
Guido van Rossum03a24cd1990-11-18 17:37:06 +0000139
Guido van Rossum3f5da241990-12-20 15:06:42 +0000140/* Forward */
Tim Petersdbd9ba62000-07-09 03:09:57 +0000141static void freechildren(node *);
Jesus Ceae9c53182012-08-03 14:28:37 +0200142static Py_ssize_t sizeofchildren(node *n);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000143
144
145void
Thomas Wouters23c9e002000-07-22 19:20:54 +0000146PyNode_Free(node *n)
Guido van Rossum3f5da241990-12-20 15:06:42 +0000147{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000148 if (n != NULL) {
149 freechildren(n);
150 PyObject_FREE(n);
151 }
Guido van Rossum3f5da241990-12-20 15:06:42 +0000152}
153
Jesus Ceae9c53182012-08-03 14:28:37 +0200154Py_ssize_t
155_PyNode_SizeOf(node *n)
156{
157 Py_ssize_t res = 0;
158
159 if (n != NULL)
160 res = sizeof(node) + sizeofchildren(n);
161 return res;
162}
163
Guido van Rossum03a24cd1990-11-18 17:37:06 +0000164static void
Thomas Wouters23c9e002000-07-22 19:20:54 +0000165freechildren(node *n)
Guido van Rossum03a24cd1990-11-18 17:37:06 +0000166{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000167 int i;
168 for (i = NCH(n); --i >= 0; )
169 freechildren(CHILD(n, i));
170 if (n->n_child != NULL)
171 PyObject_FREE(n->n_child);
172 if (STR(n) != NULL)
173 PyObject_FREE(STR(n));
Guido van Rossum03a24cd1990-11-18 17:37:06 +0000174}
Jesus Ceae9c53182012-08-03 14:28:37 +0200175
176static Py_ssize_t
177sizeofchildren(node *n)
178{
179 Py_ssize_t res = 0;
180 int i;
181 for (i = NCH(n); --i >= 0; )
182 res += sizeofchildren(CHILD(n, i));
183 if (n->n_child != NULL)
184 /* allocated size of n->n_child array */
185 res += XXXROUNDUP(NCH(n)) * sizeof(node);
186 if (STR(n) != NULL)
187 res += strlen(STR(n)) + 1;
188 return res;
189}