Skip to content

Commit 66e18f0

Browse files
committed
py: Turn down amount of RAM parser and compiler use.
There are 2 locations in parser, and 1 in compiler, where memory allocation is not precise. In the parser it's the rule stack and result stack, in the compiler it's the array for the identifiers in the current scope. All other mallocs are exact (ie they don't allocate more than is needed). This patch adds tuning options (MP_ALLOC_*) to mpconfig.h for these 3 inexact allocations. The inexact allocations in the parser should actually be close to logarithmic: you need an exponentially larger script (absent pathological cases) to use up more room on the rule and result stacks. As such, the default allocation policy for these is now to start with a modest sized stack, but grow only in small increments. For the identifier arrays in the compiler, these now start out quite small (4 entries, since most functions don't have that many ids), and grow incrementally by 6 (since if you have more ids than 4, you probably have quite a few more, but it wouldn't be exponentially more). Partially addresses issue adafruit#560.
1 parent f01fa45 commit 66e18f0

3 files changed

Lines changed: 42 additions & 9 deletions

File tree

py/mpconfig.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,39 @@
3333
// Any options not explicitly set in mpconfigport.h will get default
3434
// values below.
3535

36+
/*****************************************************************************/
37+
/* Memory allocation policy */
38+
39+
// Initial amount for parse rule stack
40+
#ifndef MP_ALLOC_PARSE_RULE_INIT
41+
#define MP_ALLOC_PARSE_RULE_INIT (64)
42+
#endif
43+
44+
// Increment for parse rule stack
45+
#ifndef MP_ALLOC_PARSE_RULE_INC
46+
#define MP_ALLOC_PARSE_RULE_INC (16)
47+
#endif
48+
49+
// Initial amount for parse result stack
50+
#ifndef MP_ALLOC_PARSE_RESULT_INIT
51+
#define MP_ALLOC_PARSE_RESULT_INIT (32)
52+
#endif
53+
54+
// Increment for parse result stack
55+
#ifndef MP_ALLOC_PARSE_RESULT_INC
56+
#define MP_ALLOC_PARSE_RESULT_INC (16)
57+
#endif
58+
59+
// Initial amount for ids in a scope
60+
#ifndef MP_ALLOC_SCOPE_ID_INIT
61+
#define MP_ALLOC_SCOPE_ID_INIT (4)
62+
#endif
63+
64+
// Increment for ids in a scope
65+
#ifndef MP_ALLOC_SCOPE_ID_INC
66+
#define MP_ALLOC_SCOPE_ID_INC (6)
67+
#endif
68+
3669
/*****************************************************************************/
3770
/* Micro Python emitters */
3871

py/parse.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -134,13 +134,13 @@ STATIC void push_rule(parser_t *parser, int src_line, const rule_t *rule, int ar
134134
return;
135135
}
136136
if (parser->rule_stack_top >= parser->rule_stack_alloc) {
137-
rule_stack_t *rs = m_renew_maybe(rule_stack_t, parser->rule_stack, parser->rule_stack_alloc, parser->rule_stack_alloc * 2);
137+
rule_stack_t *rs = m_renew_maybe(rule_stack_t, parser->rule_stack, parser->rule_stack_alloc, parser->rule_stack_alloc + MP_ALLOC_PARSE_RULE_INC);
138138
if (rs == NULL) {
139139
memory_error(parser);
140140
return;
141141
}
142142
parser->rule_stack = rs;
143-
parser->rule_stack_alloc *= 2;
143+
parser->rule_stack_alloc += MP_ALLOC_PARSE_RULE_INC;
144144
}
145145
rule_stack_t *rs = &parser->rule_stack[parser->rule_stack_top++];
146146
rs->src_line = src_line;
@@ -263,13 +263,13 @@ STATIC void push_result_node(parser_t *parser, mp_parse_node_t pn) {
263263
return;
264264
}
265265
if (parser->result_stack_top >= parser->result_stack_alloc) {
266-
mp_parse_node_t *pn = m_renew_maybe(mp_parse_node_t, parser->result_stack, parser->result_stack_alloc, parser->result_stack_alloc * 2);
266+
mp_parse_node_t *pn = m_renew_maybe(mp_parse_node_t, parser->result_stack, parser->result_stack_alloc, parser->result_stack_alloc + MP_ALLOC_PARSE_RESULT_INC);
267267
if (pn == NULL) {
268268
memory_error(parser);
269269
return;
270270
}
271271
parser->result_stack = pn;
272-
parser->result_stack_alloc *= 2;
272+
parser->result_stack_alloc += MP_ALLOC_PARSE_RESULT_INC;
273273
}
274274
parser->result_stack[parser->result_stack_top++] = pn;
275275
}
@@ -350,11 +350,11 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, mp_p
350350

351351
parser->had_memory_error = false;
352352

353-
parser->rule_stack_alloc = 64;
353+
parser->rule_stack_alloc = MP_ALLOC_PARSE_RULE_INIT;
354354
parser->rule_stack_top = 0;
355355
parser->rule_stack = m_new(rule_stack_t, parser->rule_stack_alloc);
356356

357-
parser->result_stack_alloc = 64;
357+
parser->result_stack_alloc = MP_ALLOC_PARSE_RESULT_INIT;
358358
parser->result_stack_top = 0;
359359
parser->result_stack = m_new(mp_parse_node_t, parser->result_stack_alloc);
360360

py/scope.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ scope_t *scope_new(scope_kind_t kind, mp_parse_node_t pn, qstr source_file, uint
7171
}
7272
scope->raw_code = mp_emit_glue_new_raw_code();
7373
scope->emit_options = emit_options;
74-
scope->id_info_alloc = 8;
74+
scope->id_info_alloc = MP_ALLOC_SCOPE_ID_INIT;
7575
scope->id_info = m_new(id_info_t, scope->id_info_alloc);
7676

7777
return scope;
@@ -92,8 +92,8 @@ id_info_t *scope_find_or_add_id(scope_t *scope, qstr qstr, bool *added) {
9292

9393
// make sure we have enough memory
9494
if (scope->id_info_len >= scope->id_info_alloc) {
95-
scope->id_info = m_renew(id_info_t, scope->id_info, scope->id_info_alloc, scope->id_info_alloc * 2);
96-
scope->id_info_alloc *= 2;
95+
scope->id_info = m_renew(id_info_t, scope->id_info, scope->id_info_alloc, scope->id_info_alloc + MP_ALLOC_SCOPE_ID_INC);
96+
scope->id_info_alloc += MP_ALLOC_SCOPE_ID_INC;
9797
}
9898

9999
// add new id to end of array of all ids; this seems to match CPython

0 commit comments

Comments
 (0)