py: Rework and compress second part of bytecode prelude.
This patch compresses the second part of the bytecode prelude which contains the source file name, function name, source-line-number mapping and cell closure information. This part of the prelude now begins with a single varible length unsigned integer which encodes 2 numbers, being the byte-size of the following 2 sections in the header: the "source info section" and the "closure section". After decoding this variable unsigned integer it's possible to skip over one or both of these sections very easily. This scheme saves about 2 bytes for most functions compared to the original format: one in the case that there are no closure cells, and one because padding was eliminated.pull/1/head
parent
b5ebfadbd6
commit
c8c0fd4ca3
14
py/bc.c
14
py/bc.c
|
@ -269,19 +269,25 @@ continue2:;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the ip and skip argument names
|
// read the size part of the prelude
|
||||||
const byte *ip = code_state->ip;
|
const byte *ip = code_state->ip;
|
||||||
|
MP_BC_PRELUDE_SIZE_DECODE(ip);
|
||||||
|
|
||||||
// jump over code info (source file and line-number mapping)
|
// jump over code info (source file and line-number mapping)
|
||||||
ip += mp_decode_uint_value(ip);
|
ip += n_info;
|
||||||
|
|
||||||
// bytecode prelude: initialise closed over variables
|
// bytecode prelude: initialise closed over variables
|
||||||
size_t local_num;
|
for (; n_cell; --n_cell) {
|
||||||
while ((local_num = *ip++) != 255) {
|
size_t local_num = *ip++;
|
||||||
code_state->state[n_state - 1 - local_num] =
|
code_state->state[n_state - 1 - local_num] =
|
||||||
mp_obj_new_cell(code_state->state[n_state - 1 - local_num]);
|
mp_obj_new_cell(code_state->state[n_state - 1 - local_num]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !MICROPY_PERSISTENT_CODE
|
||||||
|
// so bytecode is aligned
|
||||||
|
ip = MP_ALIGN(ip, sizeof(mp_uint_t));
|
||||||
|
#endif
|
||||||
|
|
||||||
// now that we skipped over the prelude, set the ip for the VM
|
// now that we skipped over the prelude, set the ip for the VM
|
||||||
code_state->ip = ip;
|
code_state->ip = ip;
|
||||||
|
|
||||||
|
|
64
py/bc.h
64
py/bc.h
|
@ -42,17 +42,25 @@
|
||||||
// K = n_kwonly_args number of keyword-only arguments this function takes
|
// K = n_kwonly_args number of keyword-only arguments this function takes
|
||||||
// D = n_def_pos_args number of default positional arguments
|
// D = n_def_pos_args number of default positional arguments
|
||||||
//
|
//
|
||||||
// code_info_size : var uint | code_info_size counts bytes in this chunk
|
// prelude size : var uint
|
||||||
// simple_name : var qstr |
|
// contains two values interleaved bit-wise as: xIIIIIIC repeated
|
||||||
// source_file : var qstr |
|
// x = extension another byte follows
|
||||||
// <line number info> |
|
// I = n_info number of bytes in source info section
|
||||||
// <word alignment padding> | only needed if bytecode contains pointers
|
// C = n_cells number of bytes/cells in closure section
|
||||||
//
|
//
|
||||||
// local_num0 : byte |
|
// source info section:
|
||||||
// ... : byte |
|
// simple_name : var qstr
|
||||||
// local_numN : byte | N = num_cells
|
// source_file : var qstr
|
||||||
// 255 : byte | end of list sentinel
|
// <line number info>
|
||||||
// <bytecode> |
|
//
|
||||||
|
// closure section:
|
||||||
|
// local_num0 : byte
|
||||||
|
// ... : byte
|
||||||
|
// local_numN : byte N = n_cells-1
|
||||||
|
//
|
||||||
|
// <word alignment padding> only needed if bytecode contains pointers
|
||||||
|
//
|
||||||
|
// <bytecode>
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// constant table layout:
|
// constant table layout:
|
||||||
|
@ -122,6 +130,41 @@ do { \
|
||||||
size_t n_state, n_exc_stack, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args; \
|
size_t n_state, n_exc_stack, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args; \
|
||||||
MP_BC_PRELUDE_SIG_DECODE_INTO(ip, n_state, n_exc_stack, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args)
|
MP_BC_PRELUDE_SIG_DECODE_INTO(ip, n_state, n_exc_stack, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args)
|
||||||
|
|
||||||
|
#define MP_BC_PRELUDE_SIZE_ENCODE(I, C, out_byte, out_env) \
|
||||||
|
do { \
|
||||||
|
/* Encode bit-wise as: xIIIIIIC */ \
|
||||||
|
uint8_t z = 0; \
|
||||||
|
do { \
|
||||||
|
z = (I & 0x3f) << 1 | (C & 1); \
|
||||||
|
C >>= 1; \
|
||||||
|
I >>= 6; \
|
||||||
|
if (C | I) { \
|
||||||
|
z |= 0x80; \
|
||||||
|
} \
|
||||||
|
out_byte(out_env, z); \
|
||||||
|
} while (C | I); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define MP_BC_PRELUDE_SIZE_DECODE_INTO(ip, I, C) \
|
||||||
|
do { \
|
||||||
|
uint8_t z; \
|
||||||
|
C = 0; \
|
||||||
|
I = 0; \
|
||||||
|
for (unsigned n = 0;; ++n) { \
|
||||||
|
z = *(ip)++; \
|
||||||
|
/* xIIIIIIC */ \
|
||||||
|
C |= (z & 1) << n; \
|
||||||
|
I |= ((z & 0x7e) >> 1) << (6 * n); \
|
||||||
|
if (!(z & 0x80)) { \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define MP_BC_PRELUDE_SIZE_DECODE(ip) \
|
||||||
|
size_t n_info, n_cell; \
|
||||||
|
MP_BC_PRELUDE_SIZE_DECODE_INTO(ip, n_info, n_cell)
|
||||||
|
|
||||||
// Sentinel value for mp_code_state_t.exc_sp_idx
|
// Sentinel value for mp_code_state_t.exc_sp_idx
|
||||||
#define MP_CODE_STATE_EXC_SP_IDX_SENTINEL ((uint16_t)-1)
|
#define MP_CODE_STATE_EXC_SP_IDX_SENTINEL ((uint16_t)-1)
|
||||||
|
|
||||||
|
@ -139,7 +182,6 @@ typedef struct _mp_bytecode_prelude_t {
|
||||||
qstr qstr_block_name;
|
qstr qstr_block_name;
|
||||||
qstr qstr_source_file;
|
qstr qstr_source_file;
|
||||||
const byte *line_info;
|
const byte *line_info;
|
||||||
const byte *locals;
|
|
||||||
const byte *opcodes;
|
const byte *opcodes;
|
||||||
} mp_bytecode_prelude_t;
|
} mp_bytecode_prelude_t;
|
||||||
|
|
||||||
|
|
43
py/emitbc.c
43
py/emitbc.c
|
@ -64,6 +64,9 @@ struct _emit_t {
|
||||||
size_t bytecode_size;
|
size_t bytecode_size;
|
||||||
byte *code_base; // stores both byte code and code info
|
byte *code_base; // stores both byte code and code info
|
||||||
|
|
||||||
|
size_t n_info;
|
||||||
|
size_t n_cell;
|
||||||
|
|
||||||
#if MICROPY_PERSISTENT_CODE
|
#if MICROPY_PERSISTENT_CODE
|
||||||
uint16_t ct_cur_obj;
|
uint16_t ct_cur_obj;
|
||||||
uint16_t ct_num_obj;
|
uint16_t ct_num_obj;
|
||||||
|
@ -123,10 +126,6 @@ STATIC void emit_write_code_info_byte(emit_t* emit, byte val) {
|
||||||
*emit_get_cur_to_write_code_info(emit, 1) = val;
|
*emit_get_cur_to_write_code_info(emit, 1) = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC void emit_write_code_info_uint(emit_t* emit, mp_uint_t val) {
|
|
||||||
emit_write_uint(emit, emit_get_cur_to_write_code_info, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
STATIC void emit_write_code_info_qstr(emit_t *emit, qstr qst) {
|
STATIC void emit_write_code_info_qstr(emit_t *emit, qstr qst) {
|
||||||
#if MICROPY_PERSISTENT_CODE
|
#if MICROPY_PERSISTENT_CODE
|
||||||
assert((qst >> 16) == 0);
|
assert((qst >> 16) == 0);
|
||||||
|
@ -346,29 +345,17 @@ void mp_emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) {
|
||||||
MP_BC_PRELUDE_SIG_ENCODE(n_state, n_exc_stack, scope, emit_write_code_info_byte, emit);
|
MP_BC_PRELUDE_SIG_ENCODE(n_state, n_exc_stack, scope, emit_write_code_info_byte, emit);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write size of the rest of the code info. We don't know how big this
|
// Write number of cells and size of the source code info
|
||||||
// variable uint will be on the MP_PASS_CODE_SIZE pass so we reserve 2 bytes
|
if (pass >= MP_PASS_CODE_SIZE) {
|
||||||
// for it and hope that is enough! TODO assert this or something.
|
MP_BC_PRELUDE_SIZE_ENCODE(emit->n_info, emit->n_cell, emit_write_code_info_byte, emit);
|
||||||
if (pass == MP_PASS_EMIT) {
|
|
||||||
emit_write_code_info_uint(emit, emit->code_info_size - emit->code_info_offset);
|
|
||||||
} else {
|
|
||||||
emit_get_cur_to_write_code_info(emit, 2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emit->n_info = emit->code_info_offset;
|
||||||
|
|
||||||
// Write the name and source file of this function.
|
// Write the name and source file of this function.
|
||||||
emit_write_code_info_qstr(emit, scope->simple_name);
|
emit_write_code_info_qstr(emit, scope->simple_name);
|
||||||
emit_write_code_info_qstr(emit, scope->source_file);
|
emit_write_code_info_qstr(emit, scope->source_file);
|
||||||
|
|
||||||
// bytecode prelude: initialise closed over variables
|
|
||||||
for (int i = 0; i < scope->id_info_len; i++) {
|
|
||||||
id_info_t *id = &scope->id_info[i];
|
|
||||||
if (id->kind == ID_INFO_KIND_CELL) {
|
|
||||||
assert(id->local_num < 255);
|
|
||||||
emit_write_bytecode_raw_byte(emit, id->local_num); // write the local which should be converted to a cell
|
|
||||||
}
|
|
||||||
}
|
|
||||||
emit_write_bytecode_raw_byte(emit, 255); // end of list sentinel
|
|
||||||
|
|
||||||
#if MICROPY_PERSISTENT_CODE
|
#if MICROPY_PERSISTENT_CODE
|
||||||
emit->ct_cur_obj = 0;
|
emit->ct_cur_obj = 0;
|
||||||
emit->ct_cur_raw_code = 0;
|
emit->ct_cur_raw_code = 0;
|
||||||
|
@ -414,6 +401,20 @@ void mp_emit_bc_end_pass(emit_t *emit) {
|
||||||
|
|
||||||
emit_write_code_info_byte(emit, 0); // end of line number info
|
emit_write_code_info_byte(emit, 0); // end of line number info
|
||||||
|
|
||||||
|
// Calculate size of source code info section
|
||||||
|
emit->n_info = emit->code_info_offset - emit->n_info;
|
||||||
|
|
||||||
|
// Emit closure section of prelude
|
||||||
|
emit->n_cell = 0;
|
||||||
|
for (size_t i = 0; i < emit->scope->id_info_len; ++i) {
|
||||||
|
id_info_t *id = &emit->scope->id_info[i];
|
||||||
|
if (id->kind == ID_INFO_KIND_CELL) {
|
||||||
|
assert(id->local_num <= 255);
|
||||||
|
emit_write_code_info_byte(emit, id->local_num); // write the local which should be converted to a cell
|
||||||
|
++emit->n_cell;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if MICROPY_PERSISTENT_CODE
|
#if MICROPY_PERSISTENT_CODE
|
||||||
assert(emit->pass <= MP_PASS_STACK_SIZE || (emit->ct_num_obj == emit->ct_cur_obj));
|
assert(emit->pass <= MP_PASS_STACK_SIZE || (emit->ct_num_obj == emit->ct_cur_obj));
|
||||||
emit->ct_num_obj = emit->ct_cur_obj;
|
emit->ct_num_obj = emit->ct_cur_obj;
|
||||||
|
|
|
@ -208,6 +208,7 @@ struct _emit_t {
|
||||||
uint16_t code_state_start;
|
uint16_t code_state_start;
|
||||||
uint16_t stack_start;
|
uint16_t stack_start;
|
||||||
int stack_size;
|
int stack_size;
|
||||||
|
uint16_t n_cell;
|
||||||
|
|
||||||
uint16_t const_table_cur_obj;
|
uint16_t const_table_cur_obj;
|
||||||
uint16_t const_table_num_obj;
|
uint16_t const_table_num_obj;
|
||||||
|
@ -587,9 +588,14 @@ STATIC void emit_native_end_pass(emit_t *emit) {
|
||||||
size_t n_exc_stack = 0; // exc-stack not needed for native code
|
size_t n_exc_stack = 0; // exc-stack not needed for native code
|
||||||
MP_BC_PRELUDE_SIG_ENCODE(n_state, n_exc_stack, emit->scope, emit_native_write_code_info_byte, emit);
|
MP_BC_PRELUDE_SIG_ENCODE(n_state, n_exc_stack, emit->scope, emit_native_write_code_info_byte, emit);
|
||||||
|
|
||||||
// write code info
|
|
||||||
#if MICROPY_PERSISTENT_CODE
|
#if MICROPY_PERSISTENT_CODE
|
||||||
mp_asm_base_data(&emit->as->base, 1, 5);
|
size_t n_info = 4;
|
||||||
|
#else
|
||||||
|
size_t n_info = 1;
|
||||||
|
#endif
|
||||||
|
MP_BC_PRELUDE_SIZE_ENCODE(n_info, emit->n_cell, emit_native_write_code_info_byte, emit);
|
||||||
|
|
||||||
|
#if MICROPY_PERSISTENT_CODE
|
||||||
mp_asm_base_data(&emit->as->base, 1, emit->scope->simple_name);
|
mp_asm_base_data(&emit->as->base, 1, emit->scope->simple_name);
|
||||||
mp_asm_base_data(&emit->as->base, 1, emit->scope->simple_name >> 8);
|
mp_asm_base_data(&emit->as->base, 1, emit->scope->simple_name >> 8);
|
||||||
mp_asm_base_data(&emit->as->base, 1, emit->scope->source_file);
|
mp_asm_base_data(&emit->as->base, 1, emit->scope->source_file);
|
||||||
|
@ -599,14 +605,15 @@ STATIC void emit_native_end_pass(emit_t *emit) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// bytecode prelude: initialise closed over variables
|
// bytecode prelude: initialise closed over variables
|
||||||
|
size_t cell_start = mp_asm_base_get_code_pos(&emit->as->base);
|
||||||
for (int i = 0; i < emit->scope->id_info_len; i++) {
|
for (int i = 0; i < emit->scope->id_info_len; i++) {
|
||||||
id_info_t *id = &emit->scope->id_info[i];
|
id_info_t *id = &emit->scope->id_info[i];
|
||||||
if (id->kind == ID_INFO_KIND_CELL) {
|
if (id->kind == ID_INFO_KIND_CELL) {
|
||||||
assert(id->local_num < 255);
|
assert(id->local_num <= 255);
|
||||||
mp_asm_base_data(&emit->as->base, 1, id->local_num); // write the local which should be converted to a cell
|
mp_asm_base_data(&emit->as->base, 1, id->local_num); // write the local which should be converted to a cell
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mp_asm_base_data(&emit->as->base, 1, 255); // end of list sentinel
|
emit->n_cell = mp_asm_base_get_code_pos(&emit->as->base) - cell_start;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASM_END_PASS(emit->as);
|
ASM_END_PASS(emit->as);
|
||||||
|
|
|
@ -139,7 +139,7 @@ const mp_obj_type_t mp_type_fun_builtin_var = {
|
||||||
/* byte code functions */
|
/* byte code functions */
|
||||||
|
|
||||||
qstr mp_obj_code_get_name(const byte *code_info) {
|
qstr mp_obj_code_get_name(const byte *code_info) {
|
||||||
code_info = mp_decode_uint_skip(code_info); // skip code_info_size entry
|
MP_BC_PRELUDE_SIZE_DECODE(code_info);
|
||||||
#if MICROPY_PERSISTENT_CODE
|
#if MICROPY_PERSISTENT_CODE
|
||||||
return code_info[0] | (code_info[1] << 8);
|
return code_info[0] | (code_info[1] << 8);
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -167,11 +167,10 @@ STATIC void extract_prelude(const byte **ip, const byte **ip2, bytecode_prelude_
|
||||||
prelude->n_pos_args = n_pos_args;
|
prelude->n_pos_args = n_pos_args;
|
||||||
prelude->n_kwonly_args = n_kwonly_args;
|
prelude->n_kwonly_args = n_kwonly_args;
|
||||||
prelude->n_def_pos_args = n_def_pos_args;
|
prelude->n_def_pos_args = n_def_pos_args;
|
||||||
|
MP_BC_PRELUDE_SIZE_DECODE(*ip);
|
||||||
*ip2 = *ip;
|
*ip2 = *ip;
|
||||||
prelude->code_info_size = mp_decode_uint(ip2);
|
*ip += n_info;
|
||||||
*ip += prelude->code_info_size;
|
*ip += n_cell;
|
||||||
while (*(*ip)++ != 255) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // MICROPY_PERSISTENT_CODE_LOAD || MICROPY_PERSISTENT_CODE_SAVE
|
#endif // MICROPY_PERSISTENT_CODE_LOAD || MICROPY_PERSISTENT_CODE_SAVE
|
||||||
|
@ -286,12 +285,9 @@ STATIC void load_prelude(mp_reader_t *reader, byte **ip, byte **ip2, bytecode_pr
|
||||||
byte *ip_read = *ip;
|
byte *ip_read = *ip;
|
||||||
read_uint(reader, &ip_read); // read in n_state/etc (is effectively a var-uint)
|
read_uint(reader, &ip_read); // read in n_state/etc (is effectively a var-uint)
|
||||||
byte *ip_read_save = ip_read;
|
byte *ip_read_save = ip_read;
|
||||||
size_t code_info_size = read_uint(reader, &ip_read); // read in code_info_size
|
read_uint(reader, &ip_read); // read in n_info/n_cell (is effectively a var-uint)
|
||||||
code_info_size -= ip_read - ip_read_save; // subtract bytes taken by code_info_size itself
|
MP_BC_PRELUDE_SIZE_DECODE(ip_read_save);
|
||||||
read_bytes(reader, ip_read, code_info_size); // read remaining code info
|
read_bytes(reader, ip_read, n_info + n_cell); // read remaining code info
|
||||||
ip_read += code_info_size;
|
|
||||||
while ((*ip_read++ = read_byte(reader)) != 255) {
|
|
||||||
}
|
|
||||||
|
|
||||||
// Entire prelude has been read into *ip, now decode and extract values from it
|
// Entire prelude has been read into *ip, now decode and extract values from it
|
||||||
extract_prelude((const byte**)ip, (const byte**)ip2, prelude);
|
extract_prelude((const byte**)ip, (const byte**)ip2, prelude);
|
||||||
|
|
17
py/profile.c
17
py/profile.c
|
@ -34,7 +34,7 @@
|
||||||
|
|
||||||
STATIC uint mp_prof_bytecode_lineno(const mp_raw_code_t *rc, size_t bc) {
|
STATIC uint mp_prof_bytecode_lineno(const mp_raw_code_t *rc, size_t bc) {
|
||||||
const mp_bytecode_prelude_t *prelude = &rc->prelude;
|
const mp_bytecode_prelude_t *prelude = &rc->prelude;
|
||||||
return mp_bytecode_get_source_line(prelude->line_info, bc + prelude->opcodes - prelude->locals);
|
return mp_bytecode_get_source_line(prelude->line_info, bc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mp_prof_extract_prelude(const byte *bytecode, mp_bytecode_prelude_t *prelude) {
|
void mp_prof_extract_prelude(const byte *bytecode, mp_bytecode_prelude_t *prelude) {
|
||||||
|
@ -48,22 +48,15 @@ void mp_prof_extract_prelude(const byte *bytecode, mp_bytecode_prelude_t *prelud
|
||||||
prelude->n_kwonly_args = n_kwonly_args;
|
prelude->n_kwonly_args = n_kwonly_args;
|
||||||
prelude->n_def_pos_args = n_def_pos_args;
|
prelude->n_def_pos_args = n_def_pos_args;
|
||||||
|
|
||||||
const byte *code_info = ip;
|
MP_BC_PRELUDE_SIZE_DECODE(ip);
|
||||||
size_t code_info_size = mp_decode_uint(&ip);
|
|
||||||
|
prelude->line_info = ip + 4;
|
||||||
|
prelude->opcodes = ip + n_info + n_cell;
|
||||||
|
|
||||||
qstr block_name = ip[0] | (ip[1] << 8);
|
qstr block_name = ip[0] | (ip[1] << 8);
|
||||||
qstr source_file = ip[2] | (ip[3] << 8);
|
qstr source_file = ip[2] | (ip[3] << 8);
|
||||||
ip += 4;
|
|
||||||
prelude->qstr_block_name = block_name;
|
prelude->qstr_block_name = block_name;
|
||||||
prelude->qstr_source_file = source_file;
|
prelude->qstr_source_file = source_file;
|
||||||
|
|
||||||
prelude->line_info = ip;
|
|
||||||
prelude->locals = code_info + code_info_size;
|
|
||||||
|
|
||||||
ip = prelude->locals;
|
|
||||||
while (*ip++ != 255) {
|
|
||||||
}
|
|
||||||
prelude->opcodes = ip;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
25
py/showbc.c
25
py/showbc.c
|
@ -85,10 +85,8 @@ void mp_bytecode_print(const void *descr, const byte *ip, mp_uint_t len, const m
|
||||||
|
|
||||||
// Decode prelude
|
// Decode prelude
|
||||||
MP_BC_PRELUDE_SIG_DECODE(ip);
|
MP_BC_PRELUDE_SIG_DECODE(ip);
|
||||||
|
MP_BC_PRELUDE_SIZE_DECODE(ip);
|
||||||
const byte *code_info = ip;
|
const byte *code_info = ip;
|
||||||
mp_uint_t code_info_size = mp_decode_uint(&code_info);
|
|
||||||
ip += code_info_size;
|
|
||||||
|
|
||||||
#if MICROPY_PERSISTENT_CODE
|
#if MICROPY_PERSISTENT_CODE
|
||||||
qstr block_name = code_info[0] | (code_info[1] << 8);
|
qstr block_name = code_info[0] | (code_info[1] << 8);
|
||||||
|
@ -102,7 +100,9 @@ void mp_bytecode_print(const void *descr, const byte *ip, mp_uint_t len, const m
|
||||||
qstr_str(source_file), qstr_str(block_name), descr, mp_showbc_code_start, len);
|
qstr_str(source_file), qstr_str(block_name), descr, mp_showbc_code_start, len);
|
||||||
|
|
||||||
// raw bytecode dump
|
// raw bytecode dump
|
||||||
printf("Raw bytecode (code_info_size=" UINT_FMT ", bytecode_size=" UINT_FMT "):\n", code_info_size, len - code_info_size);
|
size_t prelude_size = ip - mp_showbc_code_start + n_info + n_cell;
|
||||||
|
printf("Raw bytecode (code_info_size=" UINT_FMT ", bytecode_size=" UINT_FMT "):\n",
|
||||||
|
prelude_size, len - prelude_size);
|
||||||
for (mp_uint_t i = 0; i < len; i++) {
|
for (mp_uint_t i = 0; i < len; i++) {
|
||||||
if (i > 0 && i % 16 == 0) {
|
if (i > 0 && i % 16 == 0) {
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
@ -121,21 +121,18 @@ void mp_bytecode_print(const void *descr, const byte *ip, mp_uint_t len, const m
|
||||||
printf("(N_STATE %u)\n", (unsigned)n_state);
|
printf("(N_STATE %u)\n", (unsigned)n_state);
|
||||||
printf("(N_EXC_STACK %u)\n", (unsigned)n_exc_stack);
|
printf("(N_EXC_STACK %u)\n", (unsigned)n_exc_stack);
|
||||||
|
|
||||||
// for printing line number info
|
// skip over code_info
|
||||||
const byte *bytecode_start = ip;
|
ip += n_info;
|
||||||
|
|
||||||
// bytecode prelude: initialise closed over variables
|
// bytecode prelude: initialise closed over variables
|
||||||
{
|
for (size_t i = 0; i < n_cell; ++i) {
|
||||||
uint local_num;
|
uint local_num = *ip++;
|
||||||
while ((local_num = *ip++) != 255) {
|
printf("(INIT_CELL %u)\n", local_num);
|
||||||
printf("(INIT_CELL %u)\n", local_num);
|
|
||||||
}
|
|
||||||
len -= ip - mp_showbc_code_start;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// print out line number info
|
// print out line number info
|
||||||
{
|
{
|
||||||
mp_int_t bc = bytecode_start - ip;
|
mp_int_t bc = 0;
|
||||||
mp_uint_t source_line = 1;
|
mp_uint_t source_line = 1;
|
||||||
printf(" bc=" INT_FMT " line=" UINT_FMT "\n", bc, source_line);
|
printf(" bc=" INT_FMT " line=" UINT_FMT "\n", bc, source_line);
|
||||||
for (const byte* ci = code_info; *ci;) {
|
for (const byte* ci = code_info; *ci;) {
|
||||||
|
@ -153,7 +150,7 @@ void mp_bytecode_print(const void *descr, const byte *ip, mp_uint_t len, const m
|
||||||
printf(" bc=" INT_FMT " line=" UINT_FMT "\n", bc, source_line);
|
printf(" bc=" INT_FMT " line=" UINT_FMT "\n", bc, source_line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mp_bytecode_print2(ip, len - 0, const_table);
|
mp_bytecode_print2(ip, len - prelude_size, const_table);
|
||||||
}
|
}
|
||||||
|
|
||||||
const byte *mp_bytecode_print_str(const byte *ip) {
|
const byte *mp_bytecode_print_str(const byte *ip) {
|
||||||
|
|
11
py/vm.c
11
py/vm.c
|
@ -1441,10 +1441,13 @@ unwind_loop:
|
||||||
&& *code_state->ip != MP_BC_RAISE_LAST) {
|
&& *code_state->ip != MP_BC_RAISE_LAST) {
|
||||||
const byte *ip = code_state->fun_bc->bytecode;
|
const byte *ip = code_state->fun_bc->bytecode;
|
||||||
MP_BC_PRELUDE_SIG_DECODE(ip);
|
MP_BC_PRELUDE_SIG_DECODE(ip);
|
||||||
size_t bc = code_state->ip - ip;
|
MP_BC_PRELUDE_SIZE_DECODE(ip);
|
||||||
size_t code_info_size = mp_decode_uint_value(ip);
|
const byte *bytecode_start = ip + n_info + n_cell;
|
||||||
ip = mp_decode_uint_skip(ip); // skip code_info_size
|
#if !MICROPY_PERSISTENT_CODE
|
||||||
bc -= code_info_size;
|
// so bytecode is aligned
|
||||||
|
bytecode_start = MP_ALIGN(bytecode_start, sizeof(mp_uint_t));
|
||||||
|
#endif
|
||||||
|
size_t bc = code_state->ip - bytecode_start;
|
||||||
#if MICROPY_PERSISTENT_CODE
|
#if MICROPY_PERSISTENT_CODE
|
||||||
qstr block_name = ip[0] | (ip[1] << 8);
|
qstr block_name = ip[0] | (ip[1] << 8);
|
||||||
qstr source_file = ip[2] | (ip[3] << 8);
|
qstr source_file = ip[2] | (ip[3] << 8);
|
||||||
|
|
|
@ -36,7 +36,7 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+):
|
||||||
arg names:
|
arg names:
|
||||||
(N_STATE 5)
|
(N_STATE 5)
|
||||||
(N_EXC_STACK 0)
|
(N_EXC_STACK 0)
|
||||||
bc=-1 line=1
|
bc=0 line=1
|
||||||
bc=0 line=4
|
bc=0 line=4
|
||||||
bc=9 line=5
|
bc=9 line=5
|
||||||
bc=12 line=6
|
bc=12 line=6
|
||||||
|
|
|
@ -5,7 +5,7 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+):
|
||||||
arg names:
|
arg names:
|
||||||
(N_STATE 3)
|
(N_STATE 3)
|
||||||
(N_EXC_STACK 0)
|
(N_EXC_STACK 0)
|
||||||
bc=-1 line=1
|
bc=0 line=1
|
||||||
########
|
########
|
||||||
bc=\\d\+ line=155
|
bc=\\d\+ line=155
|
||||||
00 MAKE_FUNCTION \.\+
|
00 MAKE_FUNCTION \.\+
|
||||||
|
@ -38,7 +38,7 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+):
|
||||||
(INIT_CELL 14)
|
(INIT_CELL 14)
|
||||||
(INIT_CELL 15)
|
(INIT_CELL 15)
|
||||||
(INIT_CELL 16)
|
(INIT_CELL 16)
|
||||||
bc=-4 line=1
|
bc=0 line=1
|
||||||
########
|
########
|
||||||
bc=\\d\+ line=126
|
bc=\\d\+ line=126
|
||||||
00 LOAD_CONST_NONE
|
00 LOAD_CONST_NONE
|
||||||
|
@ -318,7 +318,7 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+):
|
||||||
\.\+rg names:
|
\.\+rg names:
|
||||||
(N_STATE 22)
|
(N_STATE 22)
|
||||||
(N_EXC_STACK 0)
|
(N_EXC_STACK 0)
|
||||||
bc=-1 line=1
|
bc=0 line=1
|
||||||
########
|
########
|
||||||
bc=\\d\+ line=132
|
bc=\\d\+ line=132
|
||||||
00 LOAD_CONST_SMALL_INT 1
|
00 LOAD_CONST_SMALL_INT 1
|
||||||
|
@ -392,7 +392,7 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+):
|
||||||
arg names:
|
arg names:
|
||||||
(N_STATE 2)
|
(N_STATE 2)
|
||||||
(N_EXC_STACK 0)
|
(N_EXC_STACK 0)
|
||||||
bc=-1 line=1
|
bc=0 line=1
|
||||||
bc=0 line=143
|
bc=0 line=143
|
||||||
bc=3 line=144
|
bc=3 line=144
|
||||||
bc=6 line=145
|
bc=6 line=145
|
||||||
|
@ -416,7 +416,7 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+):
|
||||||
arg names:
|
arg names:
|
||||||
(N_STATE 1)
|
(N_STATE 1)
|
||||||
(N_EXC_STACK 0)
|
(N_EXC_STACK 0)
|
||||||
bc=-1 line=1
|
bc=0 line=1
|
||||||
########
|
########
|
||||||
bc=13 line=149
|
bc=13 line=149
|
||||||
00 LOAD_NAME __name__ (cache=0)
|
00 LOAD_NAME __name__ (cache=0)
|
||||||
|
@ -432,7 +432,7 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+):
|
||||||
arg names: self
|
arg names: self
|
||||||
(N_STATE 4)
|
(N_STATE 4)
|
||||||
(N_EXC_STACK 0)
|
(N_EXC_STACK 0)
|
||||||
bc=-1 line=1
|
bc=0 line=1
|
||||||
bc=0 line=156
|
bc=0 line=156
|
||||||
00 LOAD_GLOBAL super (cache=0)
|
00 LOAD_GLOBAL super (cache=0)
|
||||||
\\d\+ LOAD_GLOBAL __class__ (cache=0)
|
\\d\+ LOAD_GLOBAL __class__ (cache=0)
|
||||||
|
@ -449,7 +449,7 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+):
|
||||||
arg names: * * *
|
arg names: * * *
|
||||||
(N_STATE 9)
|
(N_STATE 9)
|
||||||
(N_EXC_STACK 0)
|
(N_EXC_STACK 0)
|
||||||
bc=-\\d\+ line=1
|
bc=0 line=1
|
||||||
bc=0 line=59
|
bc=0 line=59
|
||||||
########
|
########
|
||||||
00 LOAD_NULL
|
00 LOAD_NULL
|
||||||
|
@ -473,7 +473,7 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+):
|
||||||
arg names: * * *
|
arg names: * * *
|
||||||
(N_STATE 10)
|
(N_STATE 10)
|
||||||
(N_EXC_STACK 0)
|
(N_EXC_STACK 0)
|
||||||
bc=-\\d\+ line=1
|
bc=0 line=1
|
||||||
bc=0 line=60
|
bc=0 line=60
|
||||||
########
|
########
|
||||||
00 BUILD_LIST 0
|
00 BUILD_LIST 0
|
||||||
|
@ -494,7 +494,7 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+):
|
||||||
arg names: * * *
|
arg names: * * *
|
||||||
(N_STATE 11)
|
(N_STATE 11)
|
||||||
(N_EXC_STACK 0)
|
(N_EXC_STACK 0)
|
||||||
bc=-\\d\+ line=1
|
bc=0 line=1
|
||||||
########
|
########
|
||||||
00 BUILD_MAP 0
|
00 BUILD_MAP 0
|
||||||
02 LOAD_FAST 2
|
02 LOAD_FAST 2
|
||||||
|
@ -515,7 +515,7 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+):
|
||||||
arg names: *
|
arg names: *
|
||||||
(N_STATE 4)
|
(N_STATE 4)
|
||||||
(N_EXC_STACK 0)
|
(N_EXC_STACK 0)
|
||||||
bc=-\\d\+ line=1
|
bc=0 line=1
|
||||||
########
|
########
|
||||||
bc=\\d\+ line=113
|
bc=\\d\+ line=113
|
||||||
00 LOAD_DEREF 0
|
00 LOAD_DEREF 0
|
||||||
|
@ -534,7 +534,7 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+):
|
||||||
arg names: * b
|
arg names: * b
|
||||||
(N_STATE 4)
|
(N_STATE 4)
|
||||||
(N_EXC_STACK 0)
|
(N_EXC_STACK 0)
|
||||||
bc=-\\d\+ line=1
|
bc=0 line=1
|
||||||
########
|
########
|
||||||
bc=\\d\+ line=139
|
bc=\\d\+ line=139
|
||||||
00 LOAD_FAST 1
|
00 LOAD_FAST 1
|
||||||
|
|
|
@ -6,7 +6,7 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+):
|
||||||
arg names:
|
arg names:
|
||||||
(N_STATE 2)
|
(N_STATE 2)
|
||||||
(N_EXC_STACK 0)
|
(N_EXC_STACK 0)
|
||||||
bc=-1 line=1
|
bc=0 line=1
|
||||||
bc=0 line=3
|
bc=0 line=3
|
||||||
00 LOAD_NAME print (cache=0)
|
00 LOAD_NAME print (cache=0)
|
||||||
04 LOAD_CONST_SMALL_INT 1
|
04 LOAD_CONST_SMALL_INT 1
|
||||||
|
|
|
@ -56,8 +56,8 @@ user_files = {
|
||||||
'/mod1.mpy': (
|
'/mod1.mpy': (
|
||||||
b'M\x05\x0b\x1f\x20' # header
|
b'M\x05\x0b\x1f\x20' # header
|
||||||
|
|
||||||
b'\x24' # n bytes, bytecode
|
b'\x20' # n bytes, bytecode
|
||||||
b'\x00\x05\x00\x00\x00\x00\xff' # prelude
|
b'\x00\x08\x00\x00\x00\x00' # prelude
|
||||||
b'\x51' # LOAD_CONST_NONE
|
b'\x51' # LOAD_CONST_NONE
|
||||||
b'\x63' # RETURN_VALUE
|
b'\x63' # RETURN_VALUE
|
||||||
|
|
||||||
|
|
|
@ -142,16 +142,6 @@ def mp_opcode_format(bytecode, ip, count_var_uint):
|
||||||
ip += extra_byte
|
ip += extra_byte
|
||||||
return f, ip - ip_start
|
return f, ip - ip_start
|
||||||
|
|
||||||
def decode_uint(bytecode, ip):
|
|
||||||
unum = 0
|
|
||||||
while True:
|
|
||||||
val = bytecode[ip]
|
|
||||||
ip += 1
|
|
||||||
unum = (unum << 7) | (val & 0x7f)
|
|
||||||
if not (val & 0x80):
|
|
||||||
break
|
|
||||||
return ip, unum
|
|
||||||
|
|
||||||
def read_prelude_sig(read_byte):
|
def read_prelude_sig(read_byte):
|
||||||
z = read_byte()
|
z = read_byte()
|
||||||
# xSSSSEAA
|
# xSSSSEAA
|
||||||
|
@ -175,6 +165,20 @@ def read_prelude_sig(read_byte):
|
||||||
S += 1
|
S += 1
|
||||||
return S, E, F, A, K, D
|
return S, E, F, A, K, D
|
||||||
|
|
||||||
|
def read_prelude_size(read_byte):
|
||||||
|
I = 0
|
||||||
|
C = 0
|
||||||
|
n = 0
|
||||||
|
while True:
|
||||||
|
z = read_byte()
|
||||||
|
# xIIIIIIC
|
||||||
|
I |= ((z & 0x7e) >> 1) << (6 * n)
|
||||||
|
C |= (z & 1) << n
|
||||||
|
if not (z & 0x80):
|
||||||
|
break
|
||||||
|
n += 1
|
||||||
|
return I, C
|
||||||
|
|
||||||
def extract_prelude(bytecode, ip):
|
def extract_prelude(bytecode, ip):
|
||||||
def local_read_byte():
|
def local_read_byte():
|
||||||
b = bytecode[ip_ref[0]]
|
b = bytecode[ip_ref[0]]
|
||||||
|
@ -182,16 +186,14 @@ def extract_prelude(bytecode, ip):
|
||||||
return b
|
return b
|
||||||
ip_ref = [ip] # to close over ip in Python 2 and 3
|
ip_ref = [ip] # to close over ip in Python 2 and 3
|
||||||
n_state, n_exc_stack, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args = read_prelude_sig(local_read_byte)
|
n_state, n_exc_stack, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args = read_prelude_sig(local_read_byte)
|
||||||
|
n_info, n_cell = read_prelude_size(local_read_byte)
|
||||||
ip = ip_ref[0]
|
ip = ip_ref[0]
|
||||||
|
|
||||||
ip2, code_info_size = decode_uint(bytecode, ip)
|
ip2 = ip
|
||||||
ip += code_info_size
|
ip = ip2 + n_info + n_cell
|
||||||
while bytecode[ip] != 0xff:
|
|
||||||
ip += 1
|
|
||||||
ip += 1
|
|
||||||
# ip now points to first opcode
|
# ip now points to first opcode
|
||||||
# ip2 points to simple_name qstr
|
# ip2 points to simple_name qstr
|
||||||
return ip, ip2, (n_state, n_exc_stack, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args, code_info_size)
|
return ip, ip2, (n_state, n_exc_stack, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args)
|
||||||
|
|
||||||
class MPFunTable:
|
class MPFunTable:
|
||||||
pass
|
pass
|
||||||
|
@ -359,7 +361,6 @@ class RawCode(object):
|
||||||
print(' .qstr_block_name = %s,' % self.simple_name.qstr_id)
|
print(' .qstr_block_name = %s,' % self.simple_name.qstr_id)
|
||||||
print(' .qstr_source_file = %s,' % self.source_file.qstr_id)
|
print(' .qstr_source_file = %s,' % self.source_file.qstr_id)
|
||||||
print(' .line_info = fun_data_%s + %u,' % (self.escaped_name, 0)) # TODO
|
print(' .line_info = fun_data_%s + %u,' % (self.escaped_name, 0)) # TODO
|
||||||
print(' .locals = fun_data_%s + %u,' % (self.escaped_name, 0)) # TODO
|
|
||||||
print(' .opcodes = fun_data_%s + %u,' % (self.escaped_name, self.ip))
|
print(' .opcodes = fun_data_%s + %u,' % (self.escaped_name, self.ip))
|
||||||
print(' },')
|
print(' },')
|
||||||
print(' .line_of_definition = %u,' % 0) # TODO
|
print(' .line_of_definition = %u,' % 0) # TODO
|
||||||
|
@ -583,14 +584,11 @@ def read_obj(f):
|
||||||
|
|
||||||
def read_prelude(f, bytecode):
|
def read_prelude(f, bytecode):
|
||||||
n_state, n_exc_stack, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args = read_prelude_sig(lambda: read_byte(f, bytecode))
|
n_state, n_exc_stack, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args = read_prelude_sig(lambda: read_byte(f, bytecode))
|
||||||
l1 = bytecode.idx
|
n_info, n_cell = read_prelude_size(lambda: read_byte(f, bytecode))
|
||||||
code_info_size = read_uint(f, bytecode)
|
|
||||||
l2 = bytecode.idx
|
l2 = bytecode.idx
|
||||||
for _ in range(code_info_size - (l2 - l1)):
|
for _ in range(n_info + n_cell):
|
||||||
read_byte(f, bytecode)
|
read_byte(f, bytecode)
|
||||||
while read_byte(f, bytecode) != 255:
|
return l2, (n_state, n_exc_stack, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args)
|
||||||
pass
|
|
||||||
return l2, (n_state, n_exc_stack, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args, code_info_size)
|
|
||||||
|
|
||||||
def read_qstr_and_pack(f, bytecode, qstr_win):
|
def read_qstr_and_pack(f, bytecode, qstr_win):
|
||||||
qst = read_qstr(f, qstr_win)
|
qst = read_qstr(f, qstr_win)
|
||||||
|
|
Loading…
Reference in New Issue