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:
parent
9e3e67b1d8
commit
538c3c0a55
6
py/bc.c
6
py/bc.c
|
@ -335,7 +335,11 @@ uint mp_opcode_format(const byte *ip, size_t *opcode_size, bool count_var_uint)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (f == MP_BC_FORMAT_OFFSET) {
|
} else if (f == MP_BC_FORMAT_OFFSET) {
|
||||||
ip += 2;
|
if ((*ip & 0x80) == 0) {
|
||||||
|
ip += 1;
|
||||||
|
} else {
|
||||||
|
ip += 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ip += extra_byte;
|
ip += extra_byte;
|
||||||
}
|
}
|
||||||
|
|
34
py/bc0.h
34
py/bc0.h
|
@ -28,6 +28,18 @@
|
||||||
|
|
||||||
// MicroPython bytecode opcodes, grouped based on the format of the opcode
|
// MicroPython bytecode opcodes, grouped based on the format of the opcode
|
||||||
|
|
||||||
|
// All opcodes are encoded as a byte with an optional argument. Arguments are
|
||||||
|
// variable-length encoded so they can be as small as possible. The possible
|
||||||
|
// encodings for arguments are (ip[0] is the opcode):
|
||||||
|
//
|
||||||
|
// - unsigned relative bytecode offset:
|
||||||
|
// - if ip[1] high bit is clear then: arg = ip[1]
|
||||||
|
// - if ip[1] high bit is set then: arg = ip[1] & 0x7f | ip[2] << 7
|
||||||
|
//
|
||||||
|
// - signed relative bytecode offset:
|
||||||
|
// - if ip[1] high bit is clear then: arg = ip[1] - 0x40
|
||||||
|
// - if ip[1] high bit is set then: arg = (ip[1] & 0x7f | ip[2] << 7) - 0x4000
|
||||||
|
|
||||||
#define MP_BC_MASK_FORMAT (0xf0)
|
#define MP_BC_MASK_FORMAT (0xf0)
|
||||||
#define MP_BC_MASK_EXTRA_BYTE (0x9e)
|
#define MP_BC_MASK_EXTRA_BYTE (0x9e)
|
||||||
|
|
||||||
|
@ -101,17 +113,17 @@
|
||||||
#define MP_BC_ROT_TWO (MP_BC_BASE_BYTE_O + 0x0a)
|
#define MP_BC_ROT_TWO (MP_BC_BASE_BYTE_O + 0x0a)
|
||||||
#define MP_BC_ROT_THREE (MP_BC_BASE_BYTE_O + 0x0b)
|
#define MP_BC_ROT_THREE (MP_BC_BASE_BYTE_O + 0x0b)
|
||||||
|
|
||||||
#define MP_BC_JUMP (MP_BC_BASE_JUMP_E + 0x02) // rel byte code offset, 16-bit signed, in excess
|
#define MP_BC_UNWIND_JUMP (MP_BC_BASE_JUMP_E + 0x00) // signed relative bytecode offset; then a byte
|
||||||
#define MP_BC_POP_JUMP_IF_TRUE (MP_BC_BASE_JUMP_E + 0x03) // rel byte code offset, 16-bit signed, in excess
|
#define MP_BC_JUMP (MP_BC_BASE_JUMP_E + 0x02) // signed relative bytecode offset
|
||||||
#define MP_BC_POP_JUMP_IF_FALSE (MP_BC_BASE_JUMP_E + 0x04) // rel byte code offset, 16-bit signed, in excess
|
#define MP_BC_POP_JUMP_IF_TRUE (MP_BC_BASE_JUMP_E + 0x03) // signed relative bytecode offset
|
||||||
#define MP_BC_JUMP_IF_TRUE_OR_POP (MP_BC_BASE_JUMP_E + 0x05) // rel byte code offset, 16-bit signed, in excess
|
#define MP_BC_POP_JUMP_IF_FALSE (MP_BC_BASE_JUMP_E + 0x04) // signed relative bytecode offset
|
||||||
#define MP_BC_JUMP_IF_FALSE_OR_POP (MP_BC_BASE_JUMP_E + 0x06) // rel byte code offset, 16-bit signed, in excess
|
#define MP_BC_JUMP_IF_TRUE_OR_POP (MP_BC_BASE_JUMP_E + 0x05) // signed relative bytecode offset
|
||||||
#define MP_BC_UNWIND_JUMP (MP_BC_BASE_JUMP_E + 0x00) // rel byte code offset, 16-bit signed, in excess; then a byte
|
#define MP_BC_JUMP_IF_FALSE_OR_POP (MP_BC_BASE_JUMP_E + 0x06) // signed relative bytecode offset
|
||||||
#define MP_BC_SETUP_WITH (MP_BC_BASE_JUMP_E + 0x07) // rel byte code offset, 16-bit unsigned
|
#define MP_BC_SETUP_WITH (MP_BC_BASE_JUMP_E + 0x07) // unsigned relative bytecode offset
|
||||||
#define MP_BC_SETUP_EXCEPT (MP_BC_BASE_JUMP_E + 0x08) // rel byte code offset, 16-bit unsigned
|
#define MP_BC_SETUP_EXCEPT (MP_BC_BASE_JUMP_E + 0x08) // unsigned relative bytecode offset
|
||||||
#define MP_BC_SETUP_FINALLY (MP_BC_BASE_JUMP_E + 0x09) // rel byte code offset, 16-bit unsigned
|
#define MP_BC_SETUP_FINALLY (MP_BC_BASE_JUMP_E + 0x09) // unsigned relative bytecode offset
|
||||||
#define MP_BC_POP_EXCEPT_JUMP (MP_BC_BASE_JUMP_E + 0x0a) // rel byte code offset, 16-bit unsigned
|
#define MP_BC_POP_EXCEPT_JUMP (MP_BC_BASE_JUMP_E + 0x0a) // unsigned relative bytecode offset
|
||||||
#define MP_BC_FOR_ITER (MP_BC_BASE_JUMP_E + 0x0b) // rel byte code offset, 16-bit unsigned
|
#define MP_BC_FOR_ITER (MP_BC_BASE_JUMP_E + 0x0b) // unsigned relative bytecode offset
|
||||||
#define MP_BC_WITH_CLEANUP (MP_BC_BASE_BYTE_O + 0x0c)
|
#define MP_BC_WITH_CLEANUP (MP_BC_BASE_BYTE_O + 0x0c)
|
||||||
#define MP_BC_END_FINALLY (MP_BC_BASE_BYTE_O + 0x0d)
|
#define MP_BC_END_FINALLY (MP_BC_BASE_BYTE_O + 0x0d)
|
||||||
#define MP_BC_GET_ITER (MP_BC_BASE_BYTE_O + 0x0e)
|
#define MP_BC_GET_ITER (MP_BC_BASE_BYTE_O + 0x0e)
|
||||||
|
|
12
py/compile.c
12
py/compile.c
|
@ -219,7 +219,7 @@ STATIC void mp_emit_common_start_pass(mp_emit_common_t *emit, pass_kind_t pass)
|
||||||
} else if (pass > MP_PASS_STACK_SIZE) {
|
} else if (pass > MP_PASS_STACK_SIZE) {
|
||||||
emit->ct_cur_obj = emit->ct_cur_obj_base;
|
emit->ct_cur_obj = emit->ct_cur_obj_base;
|
||||||
}
|
}
|
||||||
if (pass == MP_PASS_EMIT) {
|
if (pass == MP_PASS_CODE_SIZE) {
|
||||||
if (emit->ct_cur_child == 0) {
|
if (emit->ct_cur_child == 0) {
|
||||||
emit->children = NULL;
|
emit->children = NULL;
|
||||||
} else {
|
} else {
|
||||||
|
@ -3020,7 +3020,7 @@ STATIC void check_for_doc_string(compiler_t *comp, mp_parse_node_t pn) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
|
STATIC bool compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
|
||||||
comp->pass = pass;
|
comp->pass = pass;
|
||||||
comp->scope_cur = scope;
|
comp->scope_cur = scope;
|
||||||
comp->next_label = 0;
|
comp->next_label = 0;
|
||||||
|
@ -3187,10 +3187,12 @@ STATIC void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
|
||||||
EMIT(return_value);
|
EMIT(return_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMIT(end_pass);
|
bool pass_complete = EMIT(end_pass);
|
||||||
|
|
||||||
// make sure we match all the exception levels
|
// make sure we match all the exception levels
|
||||||
assert(comp->cur_except_level == 0);
|
assert(comp->cur_except_level == 0);
|
||||||
|
|
||||||
|
return pass_complete;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if MICROPY_EMIT_INLINE_ASM
|
#if MICROPY_EMIT_INLINE_ASM
|
||||||
|
@ -3600,8 +3602,10 @@ mp_compiled_module_t mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr so
|
||||||
}
|
}
|
||||||
|
|
||||||
// final pass: emit code
|
// final pass: emit code
|
||||||
|
// the emitter can request multiple of these passes
|
||||||
if (comp->compile_error == MP_OBJ_NULL) {
|
if (comp->compile_error == MP_OBJ_NULL) {
|
||||||
compile_scope(comp, s, MP_PASS_EMIT);
|
while (!compile_scope(comp, s, MP_PASS_EMIT)) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ typedef enum {
|
||||||
MP_PASS_SCOPE = 1, // work out id's and their kind, and number of labels
|
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_STACK_SIZE = 2, // work out maximum stack size
|
||||||
MP_PASS_CODE_SIZE = 3, // work out code size and label offsets
|
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;
|
} pass_kind_t;
|
||||||
|
|
||||||
#define MP_EMIT_STAR_FLAG_SINGLE (0x01)
|
#define MP_EMIT_STAR_FLAG_SINGLE (0x01)
|
||||||
|
@ -116,7 +116,7 @@ typedef struct _emit_method_table_t {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void (*start_pass)(emit_t *emit, pass_kind_t pass, scope_t *scope);
|
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);
|
bool (*last_emit_was_return_value)(emit_t *emit);
|
||||||
void (*adjust_stack_size)(emit_t *emit, mp_int_t delta);
|
void (*adjust_stack_size)(emit_t *emit, mp_int_t delta);
|
||||||
void (*set_source_line)(emit_t *emit, mp_uint_t line);
|
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 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_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);
|
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_adjust_stack_size(emit_t *emit, mp_int_t delta);
|
||||||
void mp_emit_bc_set_source_line(emit_t *emit, mp_uint_t line);
|
void mp_emit_bc_set_source_line(emit_t *emit, mp_uint_t line);
|
||||||
|
|
141
py/emitbc.c
141
py/emitbc.c
|
@ -28,6 +28,7 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#include "py/mpstate.h"
|
#include "py/mpstate.h"
|
||||||
|
@ -55,8 +56,8 @@ struct _emit_t {
|
||||||
mp_uint_t last_source_line_offset;
|
mp_uint_t last_source_line_offset;
|
||||||
mp_uint_t last_source_line;
|
mp_uint_t last_source_line;
|
||||||
|
|
||||||
mp_uint_t max_num_labels;
|
size_t max_num_labels;
|
||||||
mp_uint_t *label_offsets;
|
size_t *label_offsets;
|
||||||
|
|
||||||
size_t code_info_offset;
|
size_t code_info_offset;
|
||||||
size_t code_info_size;
|
size_t code_info_size;
|
||||||
|
@ -76,11 +77,11 @@ emit_t *emit_bc_new(mp_emit_common_t *emit_common) {
|
||||||
|
|
||||||
void emit_bc_set_max_num_labels(emit_t *emit, mp_uint_t max_num_labels) {
|
void emit_bc_set_max_num_labels(emit_t *emit, mp_uint_t max_num_labels) {
|
||||||
emit->max_num_labels = max_num_labels;
|
emit->max_num_labels = max_num_labels;
|
||||||
emit->label_offsets = m_new(mp_uint_t, emit->max_num_labels);
|
emit->label_offsets = m_new(size_t, emit->max_num_labels);
|
||||||
}
|
}
|
||||||
|
|
||||||
void emit_bc_free(emit_t *emit) {
|
void emit_bc_free(emit_t *emit) {
|
||||||
m_del(mp_uint_t, emit->label_offsets, emit->max_num_labels);
|
m_del(size_t, emit->label_offsets, emit->max_num_labels);
|
||||||
m_del_obj(emit_t, emit);
|
m_del_obj(emit_t, emit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,34 +214,55 @@ STATIC void emit_write_bytecode_byte_child(emit_t *emit, int stack_adj, byte b,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// unsigned labels are relative to ip following this instruction, stored as 16 bits
|
// Emit a jump opcode to a destination label.
|
||||||
STATIC void emit_write_bytecode_byte_unsigned_label(emit_t *emit, int stack_adj, byte b1, mp_uint_t label) {
|
// The offset to the label is relative to the ip following this instruction.
|
||||||
|
// The offset is encoded as either 1 or 2 bytes, depending on how big it is.
|
||||||
|
// The encoding of this jump opcode can change size from one pass to the next,
|
||||||
|
// but it must only ever decrease in size on successive passes.
|
||||||
|
STATIC void emit_write_bytecode_byte_label(emit_t *emit, int stack_adj, byte b1, mp_uint_t label) {
|
||||||
mp_emit_bc_adjust_stack_size(emit, stack_adj);
|
mp_emit_bc_adjust_stack_size(emit, stack_adj);
|
||||||
mp_uint_t bytecode_offset;
|
|
||||||
if (emit->pass < MP_PASS_EMIT) {
|
|
||||||
bytecode_offset = 0;
|
|
||||||
} else {
|
|
||||||
bytecode_offset = emit->label_offsets[label] - emit->bytecode_offset - 3;
|
|
||||||
}
|
|
||||||
byte *c = emit_get_cur_to_write_bytecode(emit, 3);
|
|
||||||
c[0] = b1;
|
|
||||||
c[1] = bytecode_offset;
|
|
||||||
c[2] = bytecode_offset >> 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
// signed labels are relative to ip following this instruction, stored as 16 bits, in excess
|
// Determine if the jump offset is signed or unsigned, based on the opcode.
|
||||||
STATIC void emit_write_bytecode_byte_signed_label(emit_t *emit, int stack_adj, byte b1, mp_uint_t label) {
|
const bool is_signed = b1 <= MP_BC_JUMP_IF_FALSE_OR_POP;
|
||||||
mp_emit_bc_adjust_stack_size(emit, stack_adj);
|
|
||||||
int bytecode_offset;
|
// Default to a 2-byte encoding (the largest) with an unknown jump offset.
|
||||||
if (emit->pass < MP_PASS_EMIT) {
|
unsigned int jump_encoding_size = 1;
|
||||||
bytecode_offset = 0;
|
ssize_t bytecode_offset = 0;
|
||||||
} else {
|
|
||||||
bytecode_offset = emit->label_offsets[label] - emit->bytecode_offset - 3 + 0x8000;
|
// Compute the jump size and offset only when code size is known.
|
||||||
|
if (emit->pass >= MP_PASS_CODE_SIZE) {
|
||||||
|
// The -2 accounts for this jump opcode taking 2 bytes (at least).
|
||||||
|
bytecode_offset = emit->label_offsets[label] - emit->bytecode_offset - 2;
|
||||||
|
|
||||||
|
// Check if the bytecode_offset is small enough to use a 1-byte encoding.
|
||||||
|
if ((is_signed && -64 <= bytecode_offset && bytecode_offset <= 63)
|
||||||
|
|| (!is_signed && (size_t)bytecode_offset <= 127)) {
|
||||||
|
// Use a 1-byte jump offset.
|
||||||
|
jump_encoding_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adjust the offset depending on the size of the encoding of the offset.
|
||||||
|
bytecode_offset -= jump_encoding_size;
|
||||||
|
|
||||||
|
assert(is_signed || bytecode_offset >= 0);
|
||||||
}
|
}
|
||||||
byte *c = emit_get_cur_to_write_bytecode(emit, 3);
|
|
||||||
|
// Emit the opcode.
|
||||||
|
byte *c = emit_get_cur_to_write_bytecode(emit, 2 + jump_encoding_size);
|
||||||
c[0] = b1;
|
c[0] = b1;
|
||||||
c[1] = bytecode_offset;
|
if (jump_encoding_size == 0) {
|
||||||
c[2] = bytecode_offset >> 8;
|
if (is_signed) {
|
||||||
|
bytecode_offset += 0x40;
|
||||||
|
}
|
||||||
|
assert(0 <= bytecode_offset && bytecode_offset <= 0x7f);
|
||||||
|
c[1] = bytecode_offset;
|
||||||
|
} else {
|
||||||
|
if (is_signed) {
|
||||||
|
bytecode_offset += 0x4000;
|
||||||
|
}
|
||||||
|
c[1] = 0x80 | (bytecode_offset & 0x7f);
|
||||||
|
c[2] = bytecode_offset >> 7;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mp_emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) {
|
void mp_emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) {
|
||||||
|
@ -250,12 +272,6 @@ void mp_emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) {
|
||||||
emit->scope = scope;
|
emit->scope = scope;
|
||||||
emit->last_source_line_offset = 0;
|
emit->last_source_line_offset = 0;
|
||||||
emit->last_source_line = 1;
|
emit->last_source_line = 1;
|
||||||
#ifndef NDEBUG
|
|
||||||
// With debugging enabled labels are checked for unique assignment
|
|
||||||
if (pass < MP_PASS_EMIT && emit->label_offsets != NULL) {
|
|
||||||
memset(emit->label_offsets, -1, emit->max_num_labels * sizeof(mp_uint_t));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
emit->bytecode_offset = 0;
|
emit->bytecode_offset = 0;
|
||||||
emit->code_info_offset = 0;
|
emit->code_info_offset = 0;
|
||||||
|
|
||||||
|
@ -315,9 +331,9 @@ 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) {
|
||||||
if (emit->pass == MP_PASS_SCOPE) {
|
if (emit->pass == MP_PASS_SCOPE) {
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check stack is back to zero size
|
// check stack is back to zero size
|
||||||
|
@ -344,6 +360,20 @@ void mp_emit_bc_end_pass(emit_t *emit) {
|
||||||
emit->code_base = m_new0(byte, emit->code_info_size + emit->bytecode_size);
|
emit->code_base = m_new0(byte, emit->code_info_size + emit->bytecode_size);
|
||||||
|
|
||||||
} else if (emit->pass == MP_PASS_EMIT) {
|
} else if (emit->pass == MP_PASS_EMIT) {
|
||||||
|
// Code info and/or bytecode can shrink during this pass.
|
||||||
|
assert(emit->code_info_offset <= emit->code_info_size);
|
||||||
|
assert(emit->bytecode_offset <= emit->bytecode_size);
|
||||||
|
|
||||||
|
if (emit->code_info_offset != emit->code_info_size
|
||||||
|
|| emit->bytecode_offset != emit->bytecode_size) {
|
||||||
|
// Code info and/or bytecode changed size in this pass, so request the
|
||||||
|
// compiler to do another pass with these updated sizes.
|
||||||
|
emit->code_info_size = emit->code_info_offset;
|
||||||
|
emit->bytecode_size = emit->bytecode_offset;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bytecode is finalised, assign it to the raw code object.
|
||||||
mp_emit_glue_assign_bytecode(emit->scope->raw_code, emit->code_base,
|
mp_emit_glue_assign_bytecode(emit->scope->raw_code, emit->code_base,
|
||||||
#if MICROPY_PERSISTENT_CODE_SAVE || MICROPY_DEBUG_PRINTERS
|
#if MICROPY_PERSISTENT_CODE_SAVE || MICROPY_DEBUG_PRINTERS
|
||||||
emit->code_info_size + emit->bytecode_size,
|
emit->code_info_size + emit->bytecode_size,
|
||||||
|
@ -354,6 +384,8 @@ void mp_emit_bc_end_pass(emit_t *emit) {
|
||||||
#endif
|
#endif
|
||||||
emit->scope->scope_flags);
|
emit->scope->scope_flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mp_emit_bc_last_emit_was_return_value(emit_t *emit) {
|
bool mp_emit_bc_last_emit_was_return_value(emit_t *emit) {
|
||||||
|
@ -396,15 +428,16 @@ void mp_emit_bc_label_assign(emit_t *emit, mp_uint_t l) {
|
||||||
if (emit->pass == MP_PASS_SCOPE) {
|
if (emit->pass == MP_PASS_SCOPE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Label offsets can change from one pass to the next, but they must only
|
||||||
|
// decrease (ie code can only shrink). There will be multiple MP_PASS_EMIT
|
||||||
|
// stages until the labels no longer change, which is when the code size
|
||||||
|
// stays constant after a MP_PASS_EMIT.
|
||||||
assert(l < emit->max_num_labels);
|
assert(l < emit->max_num_labels);
|
||||||
if (emit->pass < MP_PASS_EMIT) {
|
assert(emit->pass == MP_PASS_STACK_SIZE || emit->bytecode_offset <= emit->label_offsets[l]);
|
||||||
// assign label offset
|
|
||||||
assert(emit->label_offsets[l] == (mp_uint_t)-1);
|
// Assign label offset.
|
||||||
emit->label_offsets[l] = emit->bytecode_offset;
|
emit->label_offsets[l] = emit->bytecode_offset;
|
||||||
} else {
|
|
||||||
// ensure label offset has not changed from MP_PASS_CODE_SIZE to MP_PASS_EMIT
|
|
||||||
assert(emit->label_offsets[l] == emit->bytecode_offset);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void mp_emit_bc_import(emit_t *emit, qstr qst, int kind) {
|
void mp_emit_bc_import(emit_t *emit, qstr qst, int kind) {
|
||||||
|
@ -552,22 +585,22 @@ void mp_emit_bc_rot_three(emit_t *emit) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void mp_emit_bc_jump(emit_t *emit, mp_uint_t label) {
|
void mp_emit_bc_jump(emit_t *emit, mp_uint_t label) {
|
||||||
emit_write_bytecode_byte_signed_label(emit, 0, MP_BC_JUMP, label);
|
emit_write_bytecode_byte_label(emit, 0, MP_BC_JUMP, label);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mp_emit_bc_pop_jump_if(emit_t *emit, bool cond, mp_uint_t label) {
|
void mp_emit_bc_pop_jump_if(emit_t *emit, bool cond, mp_uint_t label) {
|
||||||
if (cond) {
|
if (cond) {
|
||||||
emit_write_bytecode_byte_signed_label(emit, -1, MP_BC_POP_JUMP_IF_TRUE, label);
|
emit_write_bytecode_byte_label(emit, -1, MP_BC_POP_JUMP_IF_TRUE, label);
|
||||||
} else {
|
} else {
|
||||||
emit_write_bytecode_byte_signed_label(emit, -1, MP_BC_POP_JUMP_IF_FALSE, label);
|
emit_write_bytecode_byte_label(emit, -1, MP_BC_POP_JUMP_IF_FALSE, label);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mp_emit_bc_jump_if_or_pop(emit_t *emit, bool cond, mp_uint_t label) {
|
void mp_emit_bc_jump_if_or_pop(emit_t *emit, bool cond, mp_uint_t label) {
|
||||||
if (cond) {
|
if (cond) {
|
||||||
emit_write_bytecode_byte_signed_label(emit, -1, MP_BC_JUMP_IF_TRUE_OR_POP, label);
|
emit_write_bytecode_byte_label(emit, -1, MP_BC_JUMP_IF_TRUE_OR_POP, label);
|
||||||
} else {
|
} else {
|
||||||
emit_write_bytecode_byte_signed_label(emit, -1, MP_BC_JUMP_IF_FALSE_OR_POP, label);
|
emit_write_bytecode_byte_label(emit, -1, MP_BC_JUMP_IF_FALSE_OR_POP, label);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -581,9 +614,9 @@ void mp_emit_bc_unwind_jump(emit_t *emit, mp_uint_t label, mp_uint_t except_dept
|
||||||
emit_write_bytecode_raw_byte(emit, MP_BC_POP_TOP);
|
emit_write_bytecode_raw_byte(emit, MP_BC_POP_TOP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
emit_write_bytecode_byte_signed_label(emit, 0, MP_BC_JUMP, label & ~MP_EMIT_BREAK_FROM_FOR);
|
emit_write_bytecode_byte_label(emit, 0, MP_BC_JUMP, label & ~MP_EMIT_BREAK_FROM_FOR);
|
||||||
} else {
|
} else {
|
||||||
emit_write_bytecode_byte_signed_label(emit, 0, MP_BC_UNWIND_JUMP, label & ~MP_EMIT_BREAK_FROM_FOR);
|
emit_write_bytecode_byte_label(emit, 0, MP_BC_UNWIND_JUMP, label & ~MP_EMIT_BREAK_FROM_FOR);
|
||||||
emit_write_bytecode_raw_byte(emit, ((label & MP_EMIT_BREAK_FROM_FOR) ? 0x80 : 0) | except_depth);
|
emit_write_bytecode_raw_byte(emit, ((label & MP_EMIT_BREAK_FROM_FOR) ? 0x80 : 0) | except_depth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -595,7 +628,7 @@ void mp_emit_bc_setup_block(emit_t *emit, mp_uint_t label, int kind) {
|
||||||
// The SETUP_WITH opcode pops ctx_mgr from the top of the stack
|
// The SETUP_WITH opcode pops ctx_mgr from the top of the stack
|
||||||
// and then pushes 3 entries: __exit__, ctx_mgr, as_value.
|
// and then pushes 3 entries: __exit__, ctx_mgr, as_value.
|
||||||
int stack_adj = kind == MP_EMIT_SETUP_BLOCK_WITH ? 2 : 0;
|
int stack_adj = kind == MP_EMIT_SETUP_BLOCK_WITH ? 2 : 0;
|
||||||
emit_write_bytecode_byte_unsigned_label(emit, stack_adj, MP_BC_SETUP_WITH + kind, label);
|
emit_write_bytecode_byte_label(emit, stack_adj, MP_BC_SETUP_WITH + kind, label);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mp_emit_bc_with_cleanup(emit_t *emit, mp_uint_t label) {
|
void mp_emit_bc_with_cleanup(emit_t *emit, mp_uint_t label) {
|
||||||
|
@ -617,7 +650,7 @@ void mp_emit_bc_get_iter(emit_t *emit, bool use_stack) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void mp_emit_bc_for_iter(emit_t *emit, mp_uint_t label) {
|
void mp_emit_bc_for_iter(emit_t *emit, mp_uint_t label) {
|
||||||
emit_write_bytecode_byte_unsigned_label(emit, 1, MP_BC_FOR_ITER, label);
|
emit_write_bytecode_byte_label(emit, 1, MP_BC_FOR_ITER, label);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mp_emit_bc_for_iter_end(emit_t *emit) {
|
void mp_emit_bc_for_iter_end(emit_t *emit) {
|
||||||
|
@ -626,7 +659,7 @@ void mp_emit_bc_for_iter_end(emit_t *emit) {
|
||||||
|
|
||||||
void mp_emit_bc_pop_except_jump(emit_t *emit, mp_uint_t label, bool within_exc_handler) {
|
void mp_emit_bc_pop_except_jump(emit_t *emit, mp_uint_t label, bool within_exc_handler) {
|
||||||
(void)within_exc_handler;
|
(void)within_exc_handler;
|
||||||
emit_write_bytecode_byte_unsigned_label(emit, 0, MP_BC_POP_EXCEPT_JUMP, label);
|
emit_write_bytecode_byte_label(emit, 0, MP_BC_POP_EXCEPT_JUMP, label);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mp_emit_bc_unary_op(emit_t *emit, mp_unary_op_t op) {
|
void mp_emit_bc_unary_op(emit_t *emit, mp_unary_op_t op) {
|
||||||
|
|
|
@ -652,7 +652,7 @@ static inline void emit_native_write_code_info_qstr(emit_t *emit, qstr qst) {
|
||||||
mp_encode_uint(&emit->as->base, mp_asm_base_get_cur_to_write_bytes, mp_emit_common_use_qstr(emit->emit_common, qst));
|
mp_encode_uint(&emit->as->base, mp_asm_base_get_cur_to_write_bytes, mp_emit_common_use_qstr(emit->emit_common, qst));
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC void emit_native_end_pass(emit_t *emit) {
|
STATIC bool emit_native_end_pass(emit_t *emit) {
|
||||||
emit_native_global_exc_exit(emit);
|
emit_native_global_exc_exit(emit);
|
||||||
|
|
||||||
if (!emit->do_viper_types) {
|
if (!emit->do_viper_types) {
|
||||||
|
@ -736,6 +736,8 @@ STATIC void emit_native_end_pass(emit_t *emit) {
|
||||||
#endif
|
#endif
|
||||||
emit->scope->scope_flags, 0, 0);
|
emit->scope->scope_flags, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC bool emit_native_last_emit_was_return_value(emit_t *emit) {
|
STATIC bool emit_native_last_emit_was_return_value(emit_t *emit) {
|
||||||
|
|
24
py/showbc.c
24
py/showbc.c
|
@ -38,8 +38,28 @@
|
||||||
unum = (unum << 7) + (*ip & 0x7f); \
|
unum = (unum << 7) + (*ip & 0x7f); \
|
||||||
} while ((*ip++ & 0x80) != 0); \
|
} while ((*ip++ & 0x80) != 0); \
|
||||||
}
|
}
|
||||||
#define DECODE_ULABEL do { unum = (ip[0] | (ip[1] << 8)); ip += 2; } while (0)
|
|
||||||
#define DECODE_SLABEL do { unum = (ip[0] | (ip[1] << 8)) - 0x8000; ip += 2; } while (0)
|
#define DECODE_ULABEL \
|
||||||
|
do { \
|
||||||
|
if (ip[0] & 0x80) { \
|
||||||
|
unum = ((ip[0] & 0x7f) | (ip[1] << 7)); \
|
||||||
|
ip += 2; \
|
||||||
|
} else { \
|
||||||
|
unum = ip[0]; \
|
||||||
|
ip += 1; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define DECODE_SLABEL \
|
||||||
|
do { \
|
||||||
|
if (ip[0] & 0x80) { \
|
||||||
|
unum = ((ip[0] & 0x7f) | (ip[1] << 7)) - 0x4000; \
|
||||||
|
ip += 2; \
|
||||||
|
} else { \
|
||||||
|
unum = ip[0] - 0x40; \
|
||||||
|
ip += 1; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#if MICROPY_EMIT_BYTECODE_USES_QSTR_TABLE
|
#if MICROPY_EMIT_BYTECODE_USES_QSTR_TABLE
|
||||||
|
|
||||||
|
|
26
py/vm.c
26
py/vm.c
|
@ -61,8 +61,30 @@
|
||||||
do { \
|
do { \
|
||||||
unum = (unum << 7) + (*ip & 0x7f); \
|
unum = (unum << 7) + (*ip & 0x7f); \
|
||||||
} while ((*ip++ & 0x80) != 0)
|
} while ((*ip++ & 0x80) != 0)
|
||||||
#define DECODE_ULABEL size_t ulab = (ip[0] | (ip[1] << 8)); ip += 2
|
|
||||||
#define DECODE_SLABEL size_t slab = (ip[0] | (ip[1] << 8)) - 0x8000; ip += 2
|
#define DECODE_ULABEL \
|
||||||
|
size_t ulab; \
|
||||||
|
do { \
|
||||||
|
if (ip[0] & 0x80) { \
|
||||||
|
ulab = ((ip[0] & 0x7f) | (ip[1] << 7)); \
|
||||||
|
ip += 2; \
|
||||||
|
} else { \
|
||||||
|
ulab = ip[0]; \
|
||||||
|
ip += 1; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define DECODE_SLABEL \
|
||||||
|
size_t slab; \
|
||||||
|
do { \
|
||||||
|
if (ip[0] & 0x80) { \
|
||||||
|
slab = ((ip[0] & 0x7f) | (ip[1] << 7)) - 0x4000; \
|
||||||
|
ip += 2; \
|
||||||
|
} else { \
|
||||||
|
slab = ip[0] - 0x40; \
|
||||||
|
ip += 1; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#if MICROPY_EMIT_BYTECODE_USES_QSTR_TABLE
|
#if MICROPY_EMIT_BYTECODE_USES_QSTR_TABLE
|
||||||
|
|
||||||
|
|
|
@ -39,52 +39,52 @@
|
||||||
[ 13] \(rule\|arglist\)(164) (n=1)
|
[ 13] \(rule\|arglist\)(164) (n=1)
|
||||||
id(b)
|
id(b)
|
||||||
----------------
|
----------------
|
||||||
File cmdline/cmd_parsetree.py, code block '<module>' (descriptor: \.\+, bytecode @\.\+ 64 bytes)
|
File cmdline/cmd_parsetree.py, code block '<module>' (descriptor: \.\+, bytecode @\.\+ 62 bytes)
|
||||||
Raw bytecode (code_info_size=13, bytecode_size=51):
|
Raw bytecode (code_info_size=13, bytecode_size=49):
|
||||||
20 16 01 60 28 23 23 24 24 24 24 24 25 2a 00 5f
|
20 16 01 60 27 22 23 24 24 24 24 24 25 2a 00 5f
|
||||||
4b 05 00 16 02 42 f8 7f 51 16 03 10 04 16 05 23
|
4b 04 16 02 42 3a 51 16 03 10 04 16 05 23 00 16
|
||||||
00 16 06 23 01 16 07 23 02 16 08 23 03 16 09 22
|
06 23 01 16 07 23 02 16 08 23 03 16 09 22 80 7b
|
||||||
80 7b 16 0a 23 04 14 0b 11 05 36 01 16 0c 51 63
|
16 0a 23 04 14 0b 11 05 36 01 16 0c 51 63
|
||||||
arg names:
|
arg names:
|
||||||
(N_STATE 5)
|
(N_STATE 5)
|
||||||
(N_EXC_STACK 0)
|
(N_EXC_STACK 0)
|
||||||
bc=0 line=1
|
bc=0 line=1
|
||||||
bc=0 line=4
|
bc=0 line=4
|
||||||
bc=8 line=5
|
bc=7 line=5
|
||||||
bc=11 line=6
|
bc=9 line=6
|
||||||
bc=14 line=7
|
bc=12 line=7
|
||||||
bc=18 line=8
|
bc=16 line=8
|
||||||
bc=22 line=9
|
bc=20 line=9
|
||||||
bc=26 line=10
|
bc=24 line=10
|
||||||
bc=30 line=11
|
bc=28 line=11
|
||||||
bc=34 line=12
|
bc=32 line=12
|
||||||
bc=39 line=13
|
bc=37 line=13
|
||||||
00 BUILD_TUPLE 0
|
00 BUILD_TUPLE 0
|
||||||
02 GET_ITER_STACK
|
02 GET_ITER_STACK
|
||||||
03 FOR_ITER 11
|
03 FOR_ITER 9
|
||||||
06 STORE_NAME i
|
05 STORE_NAME i
|
||||||
08 JUMP 3
|
07 JUMP 3
|
||||||
11 LOAD_CONST_NONE
|
09 LOAD_CONST_NONE
|
||||||
12 STORE_NAME a
|
10 STORE_NAME a
|
||||||
14 LOAD_CONST_STRING 'str'
|
12 LOAD_CONST_STRING 'str'
|
||||||
16 STORE_NAME b
|
14 STORE_NAME b
|
||||||
18 LOAD_CONST_OBJ \.\+='a very long str that will not be interned'
|
16 LOAD_CONST_OBJ \.\+='a very long str that will not be interned'
|
||||||
20 STORE_NAME c
|
18 STORE_NAME c
|
||||||
22 LOAD_CONST_OBJ \.\+=b'bytes'
|
20 LOAD_CONST_OBJ \.\+=b'bytes'
|
||||||
24 STORE_NAME d
|
22 STORE_NAME d
|
||||||
26 LOAD_CONST_OBJ \.\+=b'a very long bytes that will not be interned'
|
24 LOAD_CONST_OBJ \.\+=b'a very long bytes that will not be interned'
|
||||||
28 STORE_NAME e
|
26 STORE_NAME e
|
||||||
30 LOAD_CONST_OBJ \.\+=123456789012345678901234567890
|
28 LOAD_CONST_OBJ \.\+=123456789012345678901234567890
|
||||||
32 STORE_NAME f
|
30 STORE_NAME f
|
||||||
34 LOAD_CONST_SMALL_INT 123
|
32 LOAD_CONST_SMALL_INT 123
|
||||||
37 STORE_NAME g
|
35 STORE_NAME g
|
||||||
39 LOAD_CONST_OBJ \.\+="fstring: '{}'"
|
37 LOAD_CONST_OBJ \.\+="fstring: '{}'"
|
||||||
41 LOAD_METHOD format
|
39 LOAD_METHOD format
|
||||||
43 LOAD_NAME b
|
41 LOAD_NAME b
|
||||||
45 CALL_METHOD n=1 nkw=0
|
43 CALL_METHOD n=1 nkw=0
|
||||||
47 STORE_NAME h
|
45 STORE_NAME h
|
||||||
49 LOAD_CONST_NONE
|
47 LOAD_CONST_NONE
|
||||||
50 RETURN_VALUE
|
48 RETURN_VALUE
|
||||||
mem: total=\\d\+, current=\\d\+, peak=\\d\+
|
mem: total=\\d\+, current=\\d\+, peak=\\d\+
|
||||||
stack: \\d\+ out of \\d\+
|
stack: \\d\+ out of \\d\+
|
||||||
GC: total: \\d\+, used: \\d\+, free: \\d\+
|
GC: total: \\d\+, used: \\d\+, free: \\d\+
|
||||||
|
|
|
@ -47,10 +47,10 @@ arg names:
|
||||||
42 IMPORT_STAR
|
42 IMPORT_STAR
|
||||||
43 LOAD_CONST_NONE
|
43 LOAD_CONST_NONE
|
||||||
44 RETURN_VALUE
|
44 RETURN_VALUE
|
||||||
File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ 48\[24\] bytes)
|
File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ 45\[68\] bytes)
|
||||||
Raw bytecode (code_info_size=8\[46\], bytecode_size=398):
|
Raw bytecode (code_info_size=8\[46\], bytecode_size=372):
|
||||||
a8 12 9\[bf\] 03 02 60 60 26 22 24 64 22 26 25 25 24
|
a8 12 9\[bf\] 03 02 60 60 26 22 24 64 22 26 25 25 24
|
||||||
26 23 63 22 22 25 23 23 31 6d 25 65 25 25 69 68
|
26 23 63 22 22 25 23 23 2f 6c 25 65 25 25 69 68
|
||||||
26 65 27 6a 62 20 23 62 2a 29 69 24 25 28 67 26
|
26 65 27 6a 62 20 23 62 2a 29 69 24 25 28 67 26
|
||||||
########
|
########
|
||||||
\.\+81 63
|
\.\+81 63
|
||||||
|
@ -80,65 +80,65 @@ arg names:
|
||||||
bc=59 line=26
|
bc=59 line=26
|
||||||
bc=62 line=27
|
bc=62 line=27
|
||||||
bc=65 line=28
|
bc=65 line=28
|
||||||
bc=82 line=29
|
bc=80 line=29
|
||||||
bc=95 line=32
|
bc=92 line=32
|
||||||
bc=100 line=33
|
bc=97 line=33
|
||||||
bc=105 line=36
|
bc=102 line=36
|
||||||
bc=110 line=37
|
bc=107 line=37
|
||||||
bc=115 line=38
|
bc=112 line=38
|
||||||
bc=124 line=41
|
bc=121 line=41
|
||||||
bc=132 line=44
|
bc=129 line=44
|
||||||
bc=138 line=45
|
bc=135 line=45
|
||||||
bc=143 line=48
|
bc=140 line=48
|
||||||
bc=150 line=49
|
bc=147 line=49
|
||||||
bc=160 line=52
|
bc=157 line=52
|
||||||
bc=162 line=55
|
bc=159 line=55
|
||||||
bc=162 line=56
|
bc=159 line=56
|
||||||
bc=165 line=57
|
bc=162 line=57
|
||||||
bc=167 line=60
|
bc=164 line=60
|
||||||
bc=177 line=61
|
bc=174 line=61
|
||||||
bc=186 line=62
|
bc=183 line=62
|
||||||
bc=195 line=65
|
bc=192 line=65
|
||||||
bc=199 line=66
|
bc=196 line=66
|
||||||
bc=204 line=67
|
bc=201 line=67
|
||||||
bc=212 line=68
|
bc=209 line=68
|
||||||
bc=219 line=71
|
bc=216 line=71
|
||||||
bc=225 line=72
|
bc=222 line=72
|
||||||
bc=232 line=73
|
bc=229 line=73
|
||||||
bc=242 line=74
|
bc=239 line=74
|
||||||
bc=250 line=77
|
bc=247 line=77
|
||||||
bc=254 line=78
|
bc=250 line=78
|
||||||
bc=260 line=80
|
bc=255 line=80
|
||||||
bc=263 line=81
|
bc=258 line=81
|
||||||
bc=266 line=82
|
bc=260 line=82
|
||||||
bc=273 line=83
|
bc=266 line=83
|
||||||
bc=276 line=84
|
bc=268 line=84
|
||||||
bc=283 line=85
|
bc=274 line=85
|
||||||
bc=289 line=88
|
bc=279 line=88
|
||||||
bc=296 line=89
|
bc=285 line=89
|
||||||
bc=301 line=92
|
bc=289 line=92
|
||||||
bc=307 line=93
|
bc=293 line=93
|
||||||
bc=310 line=94
|
bc=295 line=94
|
||||||
########
|
########
|
||||||
bc=321 line=96
|
bc=303 line=96
|
||||||
bc=329 line=98
|
bc=310 line=98
|
||||||
bc=332 line=99
|
bc=313 line=99
|
||||||
bc=335 line=100
|
bc=315 line=100
|
||||||
bc=338 line=101
|
bc=317 line=101
|
||||||
########
|
########
|
||||||
bc=346 line=103
|
bc=323 line=103
|
||||||
bc=354 line=106
|
bc=329 line=106
|
||||||
bc=359 line=107
|
bc=333 line=107
|
||||||
bc=365 line=110
|
bc=339 line=110
|
||||||
bc=368 line=111
|
bc=342 line=111
|
||||||
bc=374 line=114
|
bc=348 line=114
|
||||||
bc=374 line=117
|
bc=348 line=117
|
||||||
bc=379 line=118
|
bc=353 line=118
|
||||||
bc=391 line=121
|
bc=365 line=121
|
||||||
bc=391 line=122
|
bc=365 line=122
|
||||||
bc=392 line=123
|
bc=366 line=123
|
||||||
bc=394 line=126
|
bc=368 line=126
|
||||||
bc=396 line=127
|
bc=370 line=127
|
||||||
00 LOAD_CONST_NONE
|
00 LOAD_CONST_NONE
|
||||||
01 LOAD_CONST_FALSE
|
01 LOAD_CONST_FALSE
|
||||||
02 BINARY_OP 27 __add__
|
02 BINARY_OP 27 __add__
|
||||||
|
@ -195,216 +195,216 @@ arg names:
|
||||||
68 DUP_TOP
|
68 DUP_TOP
|
||||||
69 ROT_THREE
|
69 ROT_THREE
|
||||||
70 BINARY_OP 2 __eq__
|
70 BINARY_OP 2 __eq__
|
||||||
71 JUMP_IF_FALSE_OR_POP 79
|
71 JUMP_IF_FALSE_OR_POP 77
|
||||||
74 LOAD_FAST 1
|
73 LOAD_FAST 1
|
||||||
75 BINARY_OP 2 __eq__
|
74 BINARY_OP 2 __eq__
|
||||||
76 JUMP 81
|
75 JUMP 79
|
||||||
79 ROT_TWO
|
77 ROT_TWO
|
||||||
80 POP_TOP
|
78 POP_TOP
|
||||||
81 STORE_FAST 10
|
79 STORE_FAST 10
|
||||||
82 LOAD_FAST 0
|
80 LOAD_FAST 0
|
||||||
83 LOAD_DEREF 14
|
81 LOAD_DEREF 14
|
||||||
85 BINARY_OP 2 __eq__
|
83 BINARY_OP 2 __eq__
|
||||||
86 JUMP_IF_FALSE_OR_POP 93
|
84 JUMP_IF_FALSE_OR_POP 90
|
||||||
89 LOAD_DEREF 14
|
86 LOAD_DEREF 14
|
||||||
91 LOAD_FAST 1
|
88 LOAD_FAST 1
|
||||||
92 BINARY_OP 2 __eq__
|
89 BINARY_OP 2 __eq__
|
||||||
93 UNARY_OP 3
|
90 UNARY_OP 3
|
||||||
94 STORE_FAST 10
|
91 STORE_FAST 10
|
||||||
95 LOAD_DEREF 14
|
92 LOAD_DEREF 14
|
||||||
97 LOAD_ATTR c
|
94 LOAD_ATTR c
|
||||||
99 STORE_FAST 11
|
96 STORE_FAST 11
|
||||||
100 LOAD_FAST 11
|
97 LOAD_FAST 11
|
||||||
101 LOAD_DEREF 14
|
98 LOAD_DEREF 14
|
||||||
103 STORE_ATTR c
|
100 STORE_ATTR c
|
||||||
105 LOAD_DEREF 14
|
102 LOAD_DEREF 14
|
||||||
107 LOAD_CONST_SMALL_INT 0
|
104 LOAD_CONST_SMALL_INT 0
|
||||||
108 LOAD_SUBSCR
|
105 LOAD_SUBSCR
|
||||||
109 STORE_FAST 12
|
106 STORE_FAST 12
|
||||||
110 LOAD_FAST 12
|
107 LOAD_FAST 12
|
||||||
111 LOAD_DEREF 14
|
108 LOAD_DEREF 14
|
||||||
113 LOAD_CONST_SMALL_INT 0
|
110 LOAD_CONST_SMALL_INT 0
|
||||||
114 STORE_SUBSCR
|
111 STORE_SUBSCR
|
||||||
115 LOAD_DEREF 14
|
112 LOAD_DEREF 14
|
||||||
117 LOAD_CONST_SMALL_INT 0
|
114 LOAD_CONST_SMALL_INT 0
|
||||||
118 DUP_TOP_TWO
|
115 DUP_TOP_TWO
|
||||||
119 LOAD_SUBSCR
|
116 LOAD_SUBSCR
|
||||||
120 LOAD_FAST 12
|
117 LOAD_FAST 12
|
||||||
121 BINARY_OP 14 __iadd__
|
118 BINARY_OP 14 __iadd__
|
||||||
122 ROT_THREE
|
119 ROT_THREE
|
||||||
123 STORE_SUBSCR
|
120 STORE_SUBSCR
|
||||||
124 LOAD_DEREF 14
|
121 LOAD_DEREF 14
|
||||||
126 LOAD_CONST_NONE
|
123 LOAD_CONST_NONE
|
||||||
127 LOAD_CONST_NONE
|
124 LOAD_CONST_NONE
|
||||||
128 BUILD_SLICE 2
|
125 BUILD_SLICE 2
|
||||||
130 LOAD_SUBSCR
|
127 LOAD_SUBSCR
|
||||||
131 STORE_FAST 0
|
128 STORE_FAST 0
|
||||||
132 LOAD_FAST 1
|
129 LOAD_FAST 1
|
||||||
133 UNPACK_SEQUENCE 2
|
130 UNPACK_SEQUENCE 2
|
||||||
135 STORE_FAST 0
|
132 STORE_FAST 0
|
||||||
136 STORE_DEREF 14
|
133 STORE_DEREF 14
|
||||||
138 LOAD_FAST 0
|
135 LOAD_FAST 0
|
||||||
139 UNPACK_EX 1
|
136 UNPACK_EX 1
|
||||||
141 STORE_FAST 0
|
138 STORE_FAST 0
|
||||||
142 STORE_FAST 0
|
139 STORE_FAST 0
|
||||||
143 LOAD_DEREF 14
|
140 LOAD_DEREF 14
|
||||||
145 LOAD_FAST 0
|
142 LOAD_FAST 0
|
||||||
146 ROT_TWO
|
143 ROT_TWO
|
||||||
147 STORE_FAST 0
|
144 STORE_FAST 0
|
||||||
148 STORE_DEREF 14
|
145 STORE_DEREF 14
|
||||||
150 LOAD_FAST 1
|
147 LOAD_FAST 1
|
||||||
151 LOAD_DEREF 14
|
148 LOAD_DEREF 14
|
||||||
153 LOAD_FAST 0
|
150 LOAD_FAST 0
|
||||||
154 ROT_THREE
|
151 ROT_THREE
|
||||||
155 ROT_TWO
|
152 ROT_TWO
|
||||||
156 STORE_FAST 0
|
153 STORE_FAST 0
|
||||||
157 STORE_DEREF 14
|
154 STORE_DEREF 14
|
||||||
159 STORE_FAST 1
|
156 STORE_FAST 1
|
||||||
160 DELETE_FAST 0
|
157 DELETE_FAST 0
|
||||||
162 LOAD_FAST 0
|
159 LOAD_FAST 0
|
||||||
163 STORE_GLOBAL gl
|
160 STORE_GLOBAL gl
|
||||||
165 DELETE_GLOBAL gl
|
162 DELETE_GLOBAL gl
|
||||||
167 LOAD_FAST 14
|
164 LOAD_FAST 14
|
||||||
168 LOAD_FAST 15
|
165 LOAD_FAST 15
|
||||||
169 MAKE_CLOSURE \.\+ 2
|
166 MAKE_CLOSURE \.\+ 2
|
||||||
172 LOAD_FAST 2
|
169 LOAD_FAST 2
|
||||||
173 GET_ITER
|
170 GET_ITER
|
||||||
174 CALL_FUNCTION n=1 nkw=0
|
171 CALL_FUNCTION n=1 nkw=0
|
||||||
176 STORE_FAST 0
|
173 STORE_FAST 0
|
||||||
177 LOAD_FAST 14
|
174 LOAD_FAST 14
|
||||||
178 LOAD_FAST 15
|
175 LOAD_FAST 15
|
||||||
179 MAKE_CLOSURE \.\+ 2
|
176 MAKE_CLOSURE \.\+ 2
|
||||||
182 LOAD_FAST 2
|
179 LOAD_FAST 2
|
||||||
183 CALL_FUNCTION n=1 nkw=0
|
180 CALL_FUNCTION n=1 nkw=0
|
||||||
185 STORE_FAST 0
|
182 STORE_FAST 0
|
||||||
186 LOAD_FAST 14
|
183 LOAD_FAST 14
|
||||||
187 LOAD_FAST 15
|
184 LOAD_FAST 15
|
||||||
188 MAKE_CLOSURE \.\+ 2
|
185 MAKE_CLOSURE \.\+ 2
|
||||||
191 LOAD_FAST 2
|
188 LOAD_FAST 2
|
||||||
192 CALL_FUNCTION n=1 nkw=0
|
189 CALL_FUNCTION n=1 nkw=0
|
||||||
194 STORE_FAST 0
|
191 STORE_FAST 0
|
||||||
195 LOAD_FAST 0
|
192 LOAD_FAST 0
|
||||||
196 CALL_FUNCTION n=0 nkw=0
|
193 CALL_FUNCTION n=0 nkw=0
|
||||||
198 POP_TOP
|
195 POP_TOP
|
||||||
199 LOAD_FAST 0
|
196 LOAD_FAST 0
|
||||||
200 LOAD_CONST_SMALL_INT 1
|
197 LOAD_CONST_SMALL_INT 1
|
||||||
201 CALL_FUNCTION n=1 nkw=0
|
198 CALL_FUNCTION n=1 nkw=0
|
||||||
203 POP_TOP
|
200 POP_TOP
|
||||||
204 LOAD_FAST 0
|
201 LOAD_FAST 0
|
||||||
205 LOAD_CONST_STRING 'b'
|
202 LOAD_CONST_STRING 'b'
|
||||||
207 LOAD_CONST_SMALL_INT 1
|
204 LOAD_CONST_SMALL_INT 1
|
||||||
208 CALL_FUNCTION n=0 nkw=1
|
205 CALL_FUNCTION n=0 nkw=1
|
||||||
211 POP_TOP
|
208 POP_TOP
|
||||||
212 LOAD_FAST 0
|
209 LOAD_FAST 0
|
||||||
213 LOAD_DEREF 14
|
210 LOAD_DEREF 14
|
||||||
215 LOAD_NULL
|
212 LOAD_NULL
|
||||||
216 CALL_FUNCTION_VAR_KW n=0 nkw=0
|
213 CALL_FUNCTION_VAR_KW n=0 nkw=0
|
||||||
218 POP_TOP
|
215 POP_TOP
|
||||||
219 LOAD_FAST 0
|
216 LOAD_FAST 0
|
||||||
220 LOAD_METHOD b
|
217 LOAD_METHOD b
|
||||||
222 CALL_METHOD n=0 nkw=0
|
219 CALL_METHOD n=0 nkw=0
|
||||||
224 POP_TOP
|
221 POP_TOP
|
||||||
225 LOAD_FAST 0
|
222 LOAD_FAST 0
|
||||||
226 LOAD_METHOD b
|
223 LOAD_METHOD b
|
||||||
228 LOAD_CONST_SMALL_INT 1
|
225 LOAD_CONST_SMALL_INT 1
|
||||||
229 CALL_METHOD n=1 nkw=0
|
226 CALL_METHOD n=1 nkw=0
|
||||||
231 POP_TOP
|
228 POP_TOP
|
||||||
232 LOAD_FAST 0
|
229 LOAD_FAST 0
|
||||||
233 LOAD_METHOD b
|
230 LOAD_METHOD b
|
||||||
235 LOAD_CONST_STRING 'c'
|
232 LOAD_CONST_STRING 'c'
|
||||||
237 LOAD_CONST_SMALL_INT 1
|
234 LOAD_CONST_SMALL_INT 1
|
||||||
238 CALL_METHOD n=0 nkw=1
|
235 CALL_METHOD n=0 nkw=1
|
||||||
241 POP_TOP
|
238 POP_TOP
|
||||||
242 LOAD_FAST 0
|
239 LOAD_FAST 0
|
||||||
243 LOAD_METHOD b
|
240 LOAD_METHOD b
|
||||||
245 LOAD_FAST 1
|
242 LOAD_FAST 1
|
||||||
246 LOAD_NULL
|
243 LOAD_NULL
|
||||||
247 CALL_METHOD_VAR_KW n=0 nkw=0
|
244 CALL_METHOD_VAR_KW n=0 nkw=0
|
||||||
249 POP_TOP
|
246 POP_TOP
|
||||||
250 LOAD_FAST 0
|
247 LOAD_FAST 0
|
||||||
251 POP_JUMP_IF_FALSE 260
|
248 POP_JUMP_IF_FALSE 255
|
||||||
254 LOAD_DEREF 16
|
250 LOAD_DEREF 16
|
||||||
256 POP_TOP
|
252 POP_TOP
|
||||||
257 JUMP 263
|
253 JUMP 258
|
||||||
260 LOAD_GLOBAL y
|
255 LOAD_GLOBAL y
|
||||||
|
257 POP_TOP
|
||||||
|
258 JUMP 263
|
||||||
|
260 LOAD_DEREF 14
|
||||||
262 POP_TOP
|
262 POP_TOP
|
||||||
263 JUMP 269
|
263 LOAD_FAST 0
|
||||||
266 LOAD_DEREF 14
|
264 POP_JUMP_IF_TRUE 260
|
||||||
268 POP_TOP
|
266 JUMP 271
|
||||||
269 LOAD_FAST 0
|
268 LOAD_DEREF 14
|
||||||
270 POP_JUMP_IF_TRUE 266
|
270 POP_TOP
|
||||||
273 JUMP 279
|
271 LOAD_FAST 0
|
||||||
276 LOAD_DEREF 14
|
272 POP_JUMP_IF_FALSE 268
|
||||||
278 POP_TOP
|
274 LOAD_FAST 0
|
||||||
279 LOAD_FAST 0
|
275 JUMP_IF_TRUE_OR_POP 278
|
||||||
280 POP_JUMP_IF_FALSE 276
|
277 LOAD_FAST 0
|
||||||
283 LOAD_FAST 0
|
278 STORE_FAST 0
|
||||||
284 JUMP_IF_TRUE_OR_POP 288
|
279 LOAD_DEREF 14
|
||||||
287 LOAD_FAST 0
|
281 GET_ITER_STACK
|
||||||
288 STORE_FAST 0
|
282 FOR_ITER 289
|
||||||
289 LOAD_DEREF 14
|
284 STORE_FAST 0
|
||||||
291 GET_ITER_STACK
|
285 LOAD_FAST 1
|
||||||
292 FOR_ITER 301
|
286 POP_TOP
|
||||||
295 STORE_FAST 0
|
287 JUMP 282
|
||||||
296 LOAD_FAST 1
|
289 SETUP_FINALLY 310
|
||||||
297 POP_TOP
|
291 SETUP_EXCEPT 302
|
||||||
298 JUMP 292
|
293 JUMP 297
|
||||||
301 SETUP_FINALLY 329
|
295 JUMP 300
|
||||||
304 SETUP_EXCEPT 320
|
297 LOAD_FAST 0
|
||||||
307 JUMP 313
|
298 POP_JUMP_IF_TRUE 295
|
||||||
310 JUMP 317
|
300 POP_EXCEPT_JUMP 309
|
||||||
313 LOAD_FAST 0
|
302 POP_TOP
|
||||||
314 POP_JUMP_IF_TRUE 310
|
303 LOAD_DEREF 14
|
||||||
317 POP_EXCEPT_JUMP 328
|
305 POP_TOP
|
||||||
320 POP_TOP
|
306 POP_EXCEPT_JUMP 309
|
||||||
321 LOAD_DEREF 14
|
308 END_FINALLY
|
||||||
323 POP_TOP
|
309 LOAD_CONST_NONE
|
||||||
324 POP_EXCEPT_JUMP 328
|
310 LOAD_FAST 1
|
||||||
327 END_FINALLY
|
311 POP_TOP
|
||||||
328 LOAD_CONST_NONE
|
312 END_FINALLY
|
||||||
329 LOAD_FAST 1
|
313 JUMP 326
|
||||||
330 POP_TOP
|
315 SETUP_EXCEPT 322
|
||||||
331 END_FINALLY
|
317 UNWIND_JUMP 329 1
|
||||||
332 JUMP 350
|
320 POP_EXCEPT_JUMP 326
|
||||||
335 SETUP_EXCEPT 345
|
322 POP_TOP
|
||||||
338 UNWIND_JUMP 354 1
|
323 POP_EXCEPT_JUMP 326
|
||||||
342 POP_EXCEPT_JUMP 350
|
325 END_FINALLY
|
||||||
345 POP_TOP
|
326 LOAD_FAST 0
|
||||||
346 POP_EXCEPT_JUMP 350
|
327 POP_JUMP_IF_TRUE 315
|
||||||
349 END_FINALLY
|
329 LOAD_FAST 0
|
||||||
350 LOAD_FAST 0
|
330 SETUP_WITH 337
|
||||||
351 POP_JUMP_IF_TRUE 335
|
332 POP_TOP
|
||||||
354 LOAD_FAST 0
|
333 LOAD_DEREF 14
|
||||||
355 SETUP_WITH 363
|
335 POP_TOP
|
||||||
358 POP_TOP
|
336 LOAD_CONST_NONE
|
||||||
359 LOAD_DEREF 14
|
337 WITH_CLEANUP
|
||||||
361 POP_TOP
|
338 END_FINALLY
|
||||||
362 LOAD_CONST_NONE
|
339 LOAD_CONST_SMALL_INT 1
|
||||||
363 WITH_CLEANUP
|
340 STORE_DEREF 16
|
||||||
364 END_FINALLY
|
342 LOAD_FAST_N 16
|
||||||
365 LOAD_CONST_SMALL_INT 1
|
344 MAKE_CLOSURE \.\+ 1
|
||||||
366 STORE_DEREF 16
|
347 STORE_FAST 13
|
||||||
368 LOAD_FAST_N 16
|
348 LOAD_CONST_SMALL_INT 0
|
||||||
370 MAKE_CLOSURE \.\+ 1
|
349 LOAD_CONST_NONE
|
||||||
373 STORE_FAST 13
|
350 IMPORT_NAME 'a'
|
||||||
374 LOAD_CONST_SMALL_INT 0
|
352 STORE_FAST 0
|
||||||
375 LOAD_CONST_NONE
|
353 LOAD_CONST_SMALL_INT 0
|
||||||
376 IMPORT_NAME 'a'
|
354 LOAD_CONST_STRING 'b'
|
||||||
378 STORE_FAST 0
|
356 BUILD_TUPLE 1
|
||||||
379 LOAD_CONST_SMALL_INT 0
|
358 IMPORT_NAME 'a'
|
||||||
380 LOAD_CONST_STRING 'b'
|
360 IMPORT_FROM 'b'
|
||||||
382 BUILD_TUPLE 1
|
362 STORE_DEREF 14
|
||||||
384 IMPORT_NAME 'a'
|
364 POP_TOP
|
||||||
386 IMPORT_FROM 'b'
|
365 RAISE_LAST
|
||||||
388 STORE_DEREF 14
|
366 LOAD_CONST_SMALL_INT 1
|
||||||
390 POP_TOP
|
367 RAISE_OBJ
|
||||||
391 RAISE_LAST
|
368 LOAD_CONST_NONE
|
||||||
392 LOAD_CONST_SMALL_INT 1
|
369 RETURN_VALUE
|
||||||
393 RAISE_OBJ
|
370 LOAD_CONST_SMALL_INT 1
|
||||||
394 LOAD_CONST_NONE
|
371 RETURN_VALUE
|
||||||
395 RETURN_VALUE
|
|
||||||
396 LOAD_CONST_SMALL_INT 1
|
|
||||||
397 RETURN_VALUE
|
|
||||||
File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ 59 bytes)
|
File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ 59 bytes)
|
||||||
Raw bytecode (code_info_size=8, bytecode_size=51):
|
Raw bytecode (code_info_size=8, bytecode_size=51):
|
||||||
a8 10 0a 02 80 82 34 38 81 57 c0 57 c1 57 c2 57
|
a8 10 0a 02 80 82 34 38 81 57 c0 57 c1 57 c2 57
|
||||||
|
@ -539,10 +539,10 @@ arg names: self
|
||||||
09 POP_TOP
|
09 POP_TOP
|
||||||
10 LOAD_CONST_NONE
|
10 LOAD_CONST_NONE
|
||||||
11 RETURN_VALUE
|
11 RETURN_VALUE
|
||||||
File cmdline/cmd_showbc.py, code block '<genexpr>' (descriptor: \.\+, bytecode @\.\+ 31 bytes)
|
File cmdline/cmd_showbc.py, code block '<genexpr>' (descriptor: \.\+, bytecode @\.\+ 28 bytes)
|
||||||
Raw bytecode (code_info_size=9, bytecode_size=22):
|
Raw bytecode (code_info_size=9, bytecode_size=19):
|
||||||
c3 40 0c 12 04 04 04 80 3b 53 b2 53 53 4b 0d 00
|
c3 40 0c 12 04 04 04 80 3b 53 b2 53 53 4b 0b c3
|
||||||
c3 25 01 44 f7 7f 25 00 67 59 42 f0 7f 51 63
|
25 01 44 39 25 00 67 59 42 33 51 63
|
||||||
arg names: * * *
|
arg names: * * *
|
||||||
(N_STATE 9)
|
(N_STATE 9)
|
||||||
(N_EXC_STACK 0)
|
(N_EXC_STACK 0)
|
||||||
|
@ -552,20 +552,20 @@ arg names: * * *
|
||||||
01 LOAD_FAST 2
|
01 LOAD_FAST 2
|
||||||
02 LOAD_NULL
|
02 LOAD_NULL
|
||||||
03 LOAD_NULL
|
03 LOAD_NULL
|
||||||
04 FOR_ITER 20
|
04 FOR_ITER 17
|
||||||
07 STORE_FAST 3
|
06 STORE_FAST 3
|
||||||
08 LOAD_DEREF 1
|
07 LOAD_DEREF 1
|
||||||
10 POP_JUMP_IF_FALSE 4
|
09 POP_JUMP_IF_FALSE 4
|
||||||
13 LOAD_DEREF 0
|
11 LOAD_DEREF 0
|
||||||
15 YIELD_VALUE
|
13 YIELD_VALUE
|
||||||
16 POP_TOP
|
14 POP_TOP
|
||||||
17 JUMP 4
|
15 JUMP 4
|
||||||
20 LOAD_CONST_NONE
|
17 LOAD_CONST_NONE
|
||||||
21 RETURN_VALUE
|
18 RETURN_VALUE
|
||||||
File cmdline/cmd_showbc.py, code block '<listcomp>' (descriptor: \.\+, bytecode @\.\+ 29 bytes)
|
File cmdline/cmd_showbc.py, code block '<listcomp>' (descriptor: \.\+, bytecode @\.\+ 26 bytes)
|
||||||
Raw bytecode (code_info_size=8, bytecode_size=21):
|
Raw bytecode (code_info_size=8, bytecode_size=18):
|
||||||
4b 0c 14 04 04 04 80 3c 2b 00 b2 5f 4b 0d 00 c3
|
4b 0c 14 04 04 04 80 3c 2b 00 b2 5f 4b 0b c3 25
|
||||||
25 01 44 f7 7f 25 00 2f 14 42 f0 7f 63
|
01 44 39 25 00 2f 14 42 33 63
|
||||||
arg names: * * *
|
arg names: * * *
|
||||||
(N_STATE 10)
|
(N_STATE 10)
|
||||||
(N_EXC_STACK 0)
|
(N_EXC_STACK 0)
|
||||||
|
@ -574,18 +574,18 @@ arg names: * * *
|
||||||
00 BUILD_LIST 0
|
00 BUILD_LIST 0
|
||||||
02 LOAD_FAST 2
|
02 LOAD_FAST 2
|
||||||
03 GET_ITER_STACK
|
03 GET_ITER_STACK
|
||||||
04 FOR_ITER 20
|
04 FOR_ITER 17
|
||||||
07 STORE_FAST 3
|
06 STORE_FAST 3
|
||||||
08 LOAD_DEREF 1
|
07 LOAD_DEREF 1
|
||||||
10 POP_JUMP_IF_FALSE 4
|
09 POP_JUMP_IF_FALSE 4
|
||||||
13 LOAD_DEREF 0
|
11 LOAD_DEREF 0
|
||||||
15 STORE_COMP 20
|
13 STORE_COMP 20
|
||||||
17 JUMP 4
|
15 JUMP 4
|
||||||
20 RETURN_VALUE
|
17 RETURN_VALUE
|
||||||
File cmdline/cmd_showbc.py, code block '<dictcomp>' (descriptor: \.\+, bytecode @\.\+ 31 bytes)
|
File cmdline/cmd_showbc.py, code block '<dictcomp>' (descriptor: \.\+, bytecode @\.\+ 28 bytes)
|
||||||
Raw bytecode (code_info_size=8, bytecode_size=23):
|
Raw bytecode (code_info_size=8, bytecode_size=20):
|
||||||
53 0c 15 04 04 04 80 3d 2c 00 b2 5f 4b 0f 00 c3
|
53 0c 15 04 04 04 80 3d 2c 00 b2 5f 4b 0d c3 25
|
||||||
25 01 44 f7 7f 25 00 25 00 2f 19 42 ee 7f 63
|
01 44 39 25 00 25 00 2f 19 42 31 63
|
||||||
arg names: * * *
|
arg names: * * *
|
||||||
(N_STATE 11)
|
(N_STATE 11)
|
||||||
(N_EXC_STACK 0)
|
(N_EXC_STACK 0)
|
||||||
|
@ -594,15 +594,15 @@ arg names: * * *
|
||||||
00 BUILD_MAP 0
|
00 BUILD_MAP 0
|
||||||
02 LOAD_FAST 2
|
02 LOAD_FAST 2
|
||||||
03 GET_ITER_STACK
|
03 GET_ITER_STACK
|
||||||
04 FOR_ITER 22
|
04 FOR_ITER 19
|
||||||
07 STORE_FAST 3
|
06 STORE_FAST 3
|
||||||
08 LOAD_DEREF 1
|
07 LOAD_DEREF 1
|
||||||
10 POP_JUMP_IF_FALSE 4
|
09 POP_JUMP_IF_FALSE 4
|
||||||
|
11 LOAD_DEREF 0
|
||||||
13 LOAD_DEREF 0
|
13 LOAD_DEREF 0
|
||||||
15 LOAD_DEREF 0
|
15 STORE_COMP 25
|
||||||
17 STORE_COMP 25
|
17 JUMP 4
|
||||||
19 JUMP 4
|
19 RETURN_VALUE
|
||||||
22 RETURN_VALUE
|
|
||||||
File cmdline/cmd_showbc.py, code block 'closure' (descriptor: \.\+, bytecode @\.\+ 20 bytes)
|
File cmdline/cmd_showbc.py, code block 'closure' (descriptor: \.\+, bytecode @\.\+ 20 bytes)
|
||||||
Raw bytecode (code_info_size=8, bytecode_size=12):
|
Raw bytecode (code_info_size=8, bytecode_size=12):
|
||||||
19 0c 16 04 80 6f 25 23 25 00 81 f2 c1 81 27 00
|
19 0c 16 04 80 6f 25 23 25 00 81 f2 c1 81 27 00
|
||||||
|
|
|
@ -527,6 +527,7 @@ def run_tests(pyb, tests, args, result_dir, num_threads=1):
|
||||||
"micropython/opt_level_lineno.py"
|
"micropython/opt_level_lineno.py"
|
||||||
) # native doesn't have proper traceback info
|
) # native doesn't have proper traceback info
|
||||||
skip_tests.add("micropython/schedule.py") # native code doesn't check pending events
|
skip_tests.add("micropython/schedule.py") # native code doesn't check pending events
|
||||||
|
skip_tests.add("stress/bytecode_limit.py") # bytecode specific test
|
||||||
|
|
||||||
def run_one_test(test_file):
|
def run_one_test(test_file):
|
||||||
test_file = test_file.replace("\\", "/")
|
test_file = test_file.replace("\\", "/")
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
# Test the limits of bytecode generation.
|
||||||
|
|
||||||
|
body = " with f()()() as a:\n try:\n f()()()\n except Exception:\n pass\n"
|
||||||
|
|
||||||
|
# Test changing size of code info (source line/bytecode mapping) due to changing
|
||||||
|
# bytecode size in the final passes. This test is very specific to how the
|
||||||
|
# code info is encoded, and how jump offsets shrink in the final passes. This
|
||||||
|
# test should fail if the bytecode emitter doesn't correctly handle shrinking of
|
||||||
|
# the code info section.
|
||||||
|
exec(
|
||||||
|
"""
|
||||||
|
x = 0
|
||||||
|
if x:
|
||||||
|
"""
|
||||||
|
+ body * 13
|
||||||
|
+ """
|
||||||
|
x = [1 if x else 123]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
print(x)
|
||||||
|
"""
|
||||||
|
)
|
|
@ -0,0 +1 @@
|
||||||
|
[123]
|
|
@ -242,17 +242,17 @@ class Opcodes:
|
||||||
MP_BC_ROT_TWO = (MP_BC_BASE_BYTE_O + 0x0a)
|
MP_BC_ROT_TWO = (MP_BC_BASE_BYTE_O + 0x0a)
|
||||||
MP_BC_ROT_THREE = (MP_BC_BASE_BYTE_O + 0x0b)
|
MP_BC_ROT_THREE = (MP_BC_BASE_BYTE_O + 0x0b)
|
||||||
|
|
||||||
MP_BC_JUMP = (MP_BC_BASE_JUMP_E + 0x02) # rel byte code offset, 16-bit signed, in excess
|
MP_BC_UNWIND_JUMP = (MP_BC_BASE_JUMP_E + 0x00) # signed relative bytecode offset; then a byte
|
||||||
MP_BC_POP_JUMP_IF_TRUE = (MP_BC_BASE_JUMP_E + 0x03) # rel byte code offset, 16-bit signed, in excess
|
MP_BC_JUMP = (MP_BC_BASE_JUMP_E + 0x02) # signed relative bytecode offset
|
||||||
MP_BC_POP_JUMP_IF_FALSE = (MP_BC_BASE_JUMP_E + 0x04) # rel byte code offset, 16-bit signed, in excess
|
MP_BC_POP_JUMP_IF_TRUE = (MP_BC_BASE_JUMP_E + 0x03) # signed relative bytecode offset
|
||||||
MP_BC_JUMP_IF_TRUE_OR_POP = (MP_BC_BASE_JUMP_E + 0x05) # rel byte code offset, 16-bit signed, in excess
|
MP_BC_POP_JUMP_IF_FALSE = (MP_BC_BASE_JUMP_E + 0x04) # signed relative bytecode offset
|
||||||
MP_BC_JUMP_IF_FALSE_OR_POP = (MP_BC_BASE_JUMP_E + 0x06) # rel byte code offset, 16-bit signed, in excess
|
MP_BC_JUMP_IF_TRUE_OR_POP = (MP_BC_BASE_JUMP_E + 0x05) # signed relative bytecode offset
|
||||||
MP_BC_UNWIND_JUMP = (MP_BC_BASE_JUMP_E + 0x00) # rel byte code offset, 16-bit signed, in excess; then a byte
|
MP_BC_JUMP_IF_FALSE_OR_POP = (MP_BC_BASE_JUMP_E + 0x06) # signed relative bytecode offset
|
||||||
MP_BC_SETUP_WITH = (MP_BC_BASE_JUMP_E + 0x07) # rel byte code offset, 16-bit unsigned
|
MP_BC_SETUP_WITH = (MP_BC_BASE_JUMP_E + 0x07) # unsigned relative bytecode offset
|
||||||
MP_BC_SETUP_EXCEPT = (MP_BC_BASE_JUMP_E + 0x08) # rel byte code offset, 16-bit unsigned
|
MP_BC_SETUP_EXCEPT = (MP_BC_BASE_JUMP_E + 0x08) # unsigned relative bytecode offset
|
||||||
MP_BC_SETUP_FINALLY = (MP_BC_BASE_JUMP_E + 0x09) # rel byte code offset, 16-bit unsigned
|
MP_BC_SETUP_FINALLY = (MP_BC_BASE_JUMP_E + 0x09) # unsigned relative bytecode offset
|
||||||
MP_BC_POP_EXCEPT_JUMP = (MP_BC_BASE_JUMP_E + 0x0a) # rel byte code offset, 16-bit unsigned
|
MP_BC_POP_EXCEPT_JUMP = (MP_BC_BASE_JUMP_E + 0x0a) # unsigned relative bytecode offset
|
||||||
MP_BC_FOR_ITER = (MP_BC_BASE_JUMP_E + 0x0b) # rel byte code offset, 16-bit unsigned
|
MP_BC_FOR_ITER = (MP_BC_BASE_JUMP_E + 0x0b) # unsigned relative bytecode offset
|
||||||
MP_BC_WITH_CLEANUP = (MP_BC_BASE_BYTE_O + 0x0c)
|
MP_BC_WITH_CLEANUP = (MP_BC_BASE_BYTE_O + 0x0c)
|
||||||
MP_BC_END_FINALLY = (MP_BC_BASE_BYTE_O + 0x0d)
|
MP_BC_END_FINALLY = (MP_BC_BASE_BYTE_O + 0x0d)
|
||||||
MP_BC_GET_ITER = (MP_BC_BASE_BYTE_O + 0x0e)
|
MP_BC_GET_ITER = (MP_BC_BASE_BYTE_O + 0x0e)
|
||||||
|
@ -289,6 +289,16 @@ class Opcodes:
|
||||||
MP_BC_IMPORT_STAR = (MP_BC_BASE_BYTE_E + 0x09)
|
MP_BC_IMPORT_STAR = (MP_BC_BASE_BYTE_E + 0x09)
|
||||||
# fmt: on
|
# fmt: on
|
||||||
|
|
||||||
|
# Create sets of related opcodes.
|
||||||
|
ALL_OFFSET_SIGNED = (
|
||||||
|
MP_BC_UNWIND_JUMP,
|
||||||
|
MP_BC_JUMP,
|
||||||
|
MP_BC_POP_JUMP_IF_TRUE,
|
||||||
|
MP_BC_POP_JUMP_IF_FALSE,
|
||||||
|
MP_BC_JUMP_IF_TRUE_OR_POP,
|
||||||
|
MP_BC_JUMP_IF_FALSE_OR_POP,
|
||||||
|
)
|
||||||
|
|
||||||
# Create a dict mapping opcode value to opcode name.
|
# Create a dict mapping opcode value to opcode name.
|
||||||
mapping = ["unknown" for _ in range(256)]
|
mapping = ["unknown" for _ in range(256)]
|
||||||
for op_name in list(locals()):
|
for op_name in list(locals()):
|
||||||
|
@ -323,7 +333,10 @@ def mp_opcode_format(bytecode, ip, count_var_uint):
|
||||||
ip += 1
|
ip += 1
|
||||||
ip += 1
|
ip += 1
|
||||||
elif f == MP_BC_FORMAT_OFFSET:
|
elif f == MP_BC_FORMAT_OFFSET:
|
||||||
ip += 2
|
if bytecode[ip] & 0x80 == 0:
|
||||||
|
ip += 1
|
||||||
|
else:
|
||||||
|
ip += 2
|
||||||
ip += extra_byte
|
ip += extra_byte
|
||||||
return f, ip - ip_start
|
return f, ip - ip_start
|
||||||
|
|
||||||
|
@ -342,8 +355,16 @@ def mp_opcode_decode(bytecode, ip):
|
||||||
arg = arg << 7 | bytecode[ip] & 0x7F
|
arg = arg << 7 | bytecode[ip] & 0x7F
|
||||||
ip += 1
|
ip += 1
|
||||||
elif f == MP_BC_FORMAT_OFFSET:
|
elif f == MP_BC_FORMAT_OFFSET:
|
||||||
arg = bytecode[ip] | bytecode[ip + 1] << 8
|
if bytecode[ip] & 0x80 == 0:
|
||||||
ip += 2
|
arg = bytecode[ip]
|
||||||
|
ip += 1
|
||||||
|
if opcode in Opcodes.ALL_OFFSET_SIGNED:
|
||||||
|
arg -= 0x40
|
||||||
|
else:
|
||||||
|
arg = bytecode[ip] & 0x7F | bytecode[ip + 1] << 7
|
||||||
|
ip += 2
|
||||||
|
if opcode in Opcodes.ALL_OFFSET_SIGNED:
|
||||||
|
arg -= 0x4000
|
||||||
ip += extra_byte
|
ip += extra_byte
|
||||||
return f, ip - ip_start, arg
|
return f, ip - ip_start, arg
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue