diff options
author | Damien George <damien.p.george@gmail.com> | 2014-10-25 15:07:02 +0100 |
---|---|---|
committer | Damien George <damien.p.george@gmail.com> | 2014-10-25 20:23:13 +0100 |
commit | 1084b0f9c21b093618da4494508dec9ca8467e35 (patch) | |
tree | e21a6e19240346b6a449b432cbf961d7839fba4b /py/emitbc.c | |
parent | fcff4663dd5bd33eed931c7731fd133f49551b4b (diff) | |
download | micropython-1084b0f9c21b093618da4494508dec9ca8467e35.tar.gz micropython-1084b0f9c21b093618da4494508dec9ca8467e35.zip |
py: Store bytecode arg names in bytecode (were in own array).
This saves a lot of RAM for 2 reasons:
1. For functions that don't have default values, var args or var kw
args (which is a large number of functions in the general case), the
mp_obj_fun_bc_t type now fits in 1 GC block (previously needed 2 because
of the extra pointer to point to the arg_names array). So this saves 16
bytes per function (32 bytes on 64-bit machines).
2. Combining separate memory regions generally saves RAM because the
unused bytes at the end of the GC block are saved for 1 of the blocks
(since that block doesn't exist on its own anymore). So generally this
saves 8 bytes per function.
Tested by importing lots of modules:
- 64-bit Linux gave about an 8% RAM saving for 86k of used RAM.
- pyboard gave about a 6% RAM saving for 31k of used RAM.
Diffstat (limited to 'py/emitbc.c')
-rw-r--r-- | py/emitbc.c | 24 |
1 files changed, 18 insertions, 6 deletions
diff --git a/py/emitbc.c b/py/emitbc.c index 05dc79ef4f..cee6d3396c 100644 --- a/py/emitbc.c +++ b/py/emitbc.c @@ -218,6 +218,13 @@ STATIC void emit_write_bytecode_byte_uint(emit_t* emit, byte b, mp_uint_t val) { emit_write_uint(emit, emit_get_cur_to_write_bytecode, val); } +STATIC void emit_write_bytecode_prealigned_ptr(emit_t* emit, void *ptr) { + mp_uint_t *c = (mp_uint_t*)emit_get_cur_to_write_bytecode(emit, sizeof(mp_uint_t)); + // Verify thar c is already uint-aligned + assert(c == MP_ALIGN(c, sizeof(mp_uint_t))); + *c = (mp_uint_t)ptr; +} + // aligns the pointer so it is friendly to GC STATIC void emit_write_bytecode_byte_ptr(emit_t* emit, byte b, void *ptr) { emit_write_bytecode_byte(emit, b); @@ -294,7 +301,16 @@ STATIC void emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) { emit_write_code_info_qstr(emit, scope->simple_name); emit_write_code_info_qstr(emit, scope->source_file); - // bytecode prelude: local state size and exception stack size; 16 bit uints for now + // bytecode prelude: argument names (needed to resolve positional args passed as keywords) + // we store them as full word-sized objects for efficient access in mp_setup_code_state + // this is the start of the prelude and is guaranteed to be aligned on a word boundary + { + for (int i = 0; i < scope->num_pos_args + scope->num_kwonly_args; i++) { + emit_write_bytecode_prealigned_ptr(emit, MP_OBJ_NEW_QSTR(scope->id_info[i].qst)); + } + } + + // bytecode prelude: local state size and exception stack size { mp_uint_t n_state = scope->num_locals + scope->stack_size; if (n_state == 0) { @@ -358,13 +374,9 @@ STATIC void emit_bc_end_pass(emit_t *emit) { emit->code_base = m_new0(byte, emit->code_info_size + emit->bytecode_size); } else if (emit->pass == MP_PASS_EMIT) { - qstr *arg_names = m_new(qstr, emit->scope->num_pos_args + emit->scope->num_kwonly_args); - for (int i = 0; i < emit->scope->num_pos_args + emit->scope->num_kwonly_args; i++) { - arg_names[i] = emit->scope->id_info[i].qst; - } mp_emit_glue_assign_bytecode(emit->scope->raw_code, emit->code_base, emit->code_info_size + emit->bytecode_size, - emit->scope->num_pos_args, emit->scope->num_kwonly_args, arg_names, + emit->scope->num_pos_args, emit->scope->num_kwonly_args, emit->scope->scope_flags); } } |