mirror of
https://github.com/micropython/micropython.git
synced 2026-01-04 19:20:22 +01:00
py: Change jump opcodes to emit 1-byte jump offset when possible.
This commit introduces changes: - All jump opcodes are changed to have variable length arguments, of either 1 or 2 bytes (previously they were fixed at 2 bytes). In most cases only 1 byte is needed to encode the short jump offset, saving bytecode size. - The bytecode emitter now selects 1 byte jump arguments when the jump offset is guaranteed to fit in 1 byte. This is achieved by checking if the code size changed during the last pass and, if it did (if it shrank), then requesting that the compiler make another pass to get the correct offsets of the now-smaller code. This can continue multiple times until the code stabilises. The code can only ever shrink so this iteration is guaranteed to complete. In most cases no extra passes are needed, the original 4 passes are enough to get it right by the 4th pass (because the 2nd pass computes roughly the correct labels and the 3rd pass computes the correct size for the jump argument). This change to the jump opcode encoding reduces .mpy files and RAM usage (when bytecode is in RAM) by about 2% on average. The performance of the VM is not impacted, at least within measurment of the performance benchmark suite. Code size is reduced for builds that include a decent amount of frozen bytecode. ARM Cortex-M builds without any frozen code increase by about 350 bytes. Signed-off-by: Damien George <damien@micropython.org>
This commit is contained in:
@@ -43,7 +43,7 @@ typedef enum {
|
||||
MP_PASS_SCOPE = 1, // work out id's and their kind, and number of labels
|
||||
MP_PASS_STACK_SIZE = 2, // work out maximum stack size
|
||||
MP_PASS_CODE_SIZE = 3, // work out code size and label offsets
|
||||
MP_PASS_EMIT = 4, // emit code
|
||||
MP_PASS_EMIT = 4, // emit code (may be run multiple times if the emitter requests it)
|
||||
} pass_kind_t;
|
||||
|
||||
#define MP_EMIT_STAR_FLAG_SINGLE (0x01)
|
||||
@@ -116,7 +116,7 @@ typedef struct _emit_method_table_t {
|
||||
#endif
|
||||
|
||||
void (*start_pass)(emit_t *emit, pass_kind_t pass, scope_t *scope);
|
||||
void (*end_pass)(emit_t *emit);
|
||||
bool (*end_pass)(emit_t *emit);
|
||||
bool (*last_emit_was_return_value)(emit_t *emit);
|
||||
void (*adjust_stack_size)(emit_t *emit, mp_int_t delta);
|
||||
void (*set_source_line)(emit_t *emit, mp_uint_t line);
|
||||
@@ -233,7 +233,7 @@ void emit_native_xtensa_free(emit_t *emit);
|
||||
void emit_native_xtensawin_free(emit_t *emit);
|
||||
|
||||
void mp_emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope);
|
||||
void mp_emit_bc_end_pass(emit_t *emit);
|
||||
bool mp_emit_bc_end_pass(emit_t *emit);
|
||||
bool mp_emit_bc_last_emit_was_return_value(emit_t *emit);
|
||||
void mp_emit_bc_adjust_stack_size(emit_t *emit, mp_int_t delta);
|
||||
void mp_emit_bc_set_source_line(emit_t *emit, mp_uint_t line);
|
||||
|
||||
Reference in New Issue
Block a user