py/emit: Suppress unreachable bytecode/native code that follows jump.
This new logic tracks when an unconditional jump/raise occurs in the emitted code stream (bytecode or native machine code) and suppresses all subsequent code, until a label is assigned. This eliminates a lot of cases of dead code, with relatively simple logic. This commit combined with the previous one (that removed the existing dead-code finding logic) has the following code size change: bare-arm: -16 -0.028% minimal x86: -60 -0.036% unix x64: -368 -0.070% unix nanbox: -80 -0.017% stm32: -204 -0.052% PYBV10 cc3200: +0 +0.000% esp8266: -232 -0.033% GENERIC esp32: -224 -0.015% GENERIC[incl -40(data)] mimxrt: -192 -0.054% TEENSY40 renesas-ra: -200 -0.032% RA6M2_EK nrf: +28 +0.015% pca10040 rp2: -256 -0.050% PICO samd: -12 -0.009% ADAFRUIT_ITSYBITSY_M4_EXPRESS Signed-off-by: Damien George <damien@micropython.org>
This commit is contained in:
parent
e85a096302
commit
a506335524
10
py/asmbase.c
10
py/asmbase.c
@ -55,15 +55,20 @@ void mp_asm_base_start_pass(mp_asm_base_t *as, int pass) {
|
|||||||
assert(as->code_base != NULL);
|
assert(as->code_base != NULL);
|
||||||
}
|
}
|
||||||
as->pass = pass;
|
as->pass = pass;
|
||||||
|
as->suppress = false;
|
||||||
as->code_offset = 0;
|
as->code_offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// all functions must go through this one to emit bytes
|
// all functions must go through this one to emit bytes
|
||||||
// if as->pass < MP_ASM_PASS_EMIT, then this function just counts the number
|
// if as->pass < MP_ASM_PASS_EMIT, then this function just counts the number
|
||||||
// of bytes needed and returns NULL, and callers should not store any data
|
// of bytes needed and returns NULL, and callers should not store any data
|
||||||
|
// It also returns NULL if generated code should be suppressed at this point.
|
||||||
uint8_t *mp_asm_base_get_cur_to_write_bytes(void *as_in, size_t num_bytes_to_write) {
|
uint8_t *mp_asm_base_get_cur_to_write_bytes(void *as_in, size_t num_bytes_to_write) {
|
||||||
mp_asm_base_t *as = as_in;
|
mp_asm_base_t *as = as_in;
|
||||||
uint8_t *c = NULL;
|
uint8_t *c = NULL;
|
||||||
|
if (as->suppress) {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
if (as->pass == MP_ASM_PASS_EMIT) {
|
if (as->pass == MP_ASM_PASS_EMIT) {
|
||||||
assert(as->code_offset + num_bytes_to_write <= as->code_size);
|
assert(as->code_offset + num_bytes_to_write <= as->code_size);
|
||||||
c = as->code_base + as->code_offset;
|
c = as->code_base + as->code_offset;
|
||||||
@ -74,6 +79,11 @@ uint8_t *mp_asm_base_get_cur_to_write_bytes(void *as_in, size_t num_bytes_to_wri
|
|||||||
|
|
||||||
void mp_asm_base_label_assign(mp_asm_base_t *as, size_t label) {
|
void mp_asm_base_label_assign(mp_asm_base_t *as, size_t label) {
|
||||||
assert(label < as->max_num_labels);
|
assert(label < as->max_num_labels);
|
||||||
|
|
||||||
|
// Assiging a label ends any dead-code region, and all following machine
|
||||||
|
// code should be emitted (until another mp_asm_base_suppress_code() call).
|
||||||
|
as->suppress = false;
|
||||||
|
|
||||||
if (as->pass < MP_ASM_PASS_EMIT) {
|
if (as->pass < MP_ASM_PASS_EMIT) {
|
||||||
// assign label offset
|
// assign label offset
|
||||||
assert(as->label_offsets[label] == (size_t)-1);
|
assert(as->label_offsets[label] == (size_t)-1);
|
||||||
|
11
py/asmbase.h
11
py/asmbase.h
@ -33,7 +33,12 @@
|
|||||||
#define MP_ASM_PASS_EMIT (2)
|
#define MP_ASM_PASS_EMIT (2)
|
||||||
|
|
||||||
typedef struct _mp_asm_base_t {
|
typedef struct _mp_asm_base_t {
|
||||||
int pass;
|
uint8_t pass;
|
||||||
|
|
||||||
|
// Set to true using mp_asm_base_suppress_code() if the code generator
|
||||||
|
// should suppress emitted code due to it being dead code.
|
||||||
|
bool suppress;
|
||||||
|
|
||||||
size_t code_offset;
|
size_t code_offset;
|
||||||
size_t code_size;
|
size_t code_size;
|
||||||
uint8_t *code_base;
|
uint8_t *code_base;
|
||||||
@ -50,6 +55,10 @@ void mp_asm_base_label_assign(mp_asm_base_t *as, size_t label);
|
|||||||
void mp_asm_base_align(mp_asm_base_t *as, unsigned int align);
|
void mp_asm_base_align(mp_asm_base_t *as, unsigned int align);
|
||||||
void mp_asm_base_data(mp_asm_base_t *as, unsigned int bytesize, uintptr_t val);
|
void mp_asm_base_data(mp_asm_base_t *as, unsigned int bytesize, uintptr_t val);
|
||||||
|
|
||||||
|
static inline void mp_asm_base_suppress_code(mp_asm_base_t *as) {
|
||||||
|
as->suppress = true;
|
||||||
|
}
|
||||||
|
|
||||||
static inline size_t mp_asm_base_get_code_pos(mp_asm_base_t *as) {
|
static inline size_t mp_asm_base_get_code_pos(mp_asm_base_t *as) {
|
||||||
return as->code_offset;
|
return as->code_offset;
|
||||||
}
|
}
|
||||||
|
22
py/emitbc.c
22
py/emitbc.c
@ -48,6 +48,11 @@ struct _emit_t {
|
|||||||
|
|
||||||
pass_kind_t pass : 8;
|
pass_kind_t pass : 8;
|
||||||
|
|
||||||
|
// Set to true if the code generator should suppress emitted code due to it
|
||||||
|
// being dead code. This can happen when opcodes immediately follow an
|
||||||
|
// unconditional flow control (eg jump or raise).
|
||||||
|
bool suppress;
|
||||||
|
|
||||||
int stack_size;
|
int stack_size;
|
||||||
|
|
||||||
mp_emit_common_t *emit_common;
|
mp_emit_common_t *emit_common;
|
||||||
@ -140,6 +145,9 @@ STATIC void emit_write_code_info_bytes_lines(emit_t *emit, mp_uint_t bytes_to_sk
|
|||||||
// all functions must go through this one to emit byte code
|
// all functions must go through this one to emit byte code
|
||||||
STATIC uint8_t *emit_get_cur_to_write_bytecode(void *emit_in, size_t num_bytes_to_write) {
|
STATIC uint8_t *emit_get_cur_to_write_bytecode(void *emit_in, size_t num_bytes_to_write) {
|
||||||
emit_t *emit = emit_in;
|
emit_t *emit = emit_in;
|
||||||
|
if (emit->suppress) {
|
||||||
|
return emit->dummy_data;
|
||||||
|
}
|
||||||
if (emit->pass < MP_PASS_EMIT) {
|
if (emit->pass < MP_PASS_EMIT) {
|
||||||
emit->bytecode_offset += num_bytes_to_write;
|
emit->bytecode_offset += num_bytes_to_write;
|
||||||
return emit->dummy_data;
|
return emit->dummy_data;
|
||||||
@ -222,6 +230,10 @@ STATIC void emit_write_bytecode_byte_child(emit_t *emit, int stack_adj, byte b,
|
|||||||
STATIC void emit_write_bytecode_byte_label(emit_t *emit, int stack_adj, byte b1, mp_uint_t label) {
|
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);
|
||||||
|
|
||||||
|
if (emit->suppress) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Determine if the jump offset is signed or unsigned, based on the opcode.
|
// Determine if the jump offset is signed or unsigned, based on the opcode.
|
||||||
const bool is_signed = b1 <= MP_BC_POP_JUMP_IF_FALSE;
|
const bool is_signed = b1 <= MP_BC_POP_JUMP_IF_FALSE;
|
||||||
|
|
||||||
@ -271,6 +283,7 @@ STATIC void emit_write_bytecode_byte_label(emit_t *emit, int stack_adj, byte b1,
|
|||||||
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) {
|
||||||
emit->pass = pass;
|
emit->pass = pass;
|
||||||
emit->stack_size = 0;
|
emit->stack_size = 0;
|
||||||
|
emit->suppress = false;
|
||||||
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;
|
||||||
@ -426,6 +439,10 @@ void mp_emit_bc_set_source_line(emit_t *emit, mp_uint_t source_line) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void mp_emit_bc_label_assign(emit_t *emit, mp_uint_t l) {
|
void mp_emit_bc_label_assign(emit_t *emit, mp_uint_t l) {
|
||||||
|
// Assiging a label ends any dead-code region, and all following opcodes
|
||||||
|
// should be emitted (until another unconditional flow control).
|
||||||
|
emit->suppress = false;
|
||||||
|
|
||||||
mp_emit_bc_adjust_stack_size(emit, 0);
|
mp_emit_bc_adjust_stack_size(emit, 0);
|
||||||
if (emit->pass == MP_PASS_SCOPE) {
|
if (emit->pass == MP_PASS_SCOPE) {
|
||||||
return;
|
return;
|
||||||
@ -589,6 +606,7 @@ 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_label(emit, 0, MP_BC_JUMP, label);
|
emit_write_bytecode_byte_label(emit, 0, MP_BC_JUMP, label);
|
||||||
|
emit->suppress = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
@ -622,6 +640,7 @@ void mp_emit_bc_unwind_jump(emit_t *emit, mp_uint_t label, mp_uint_t except_dept
|
|||||||
emit_write_bytecode_byte_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);
|
||||||
}
|
}
|
||||||
|
emit->suppress = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mp_emit_bc_setup_block(emit_t *emit, mp_uint_t label, int kind) {
|
void mp_emit_bc_setup_block(emit_t *emit, mp_uint_t label, int kind) {
|
||||||
@ -663,6 +682,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_label(emit, 0, MP_BC_POP_EXCEPT_JUMP, label);
|
emit_write_bytecode_byte_label(emit, 0, MP_BC_POP_EXCEPT_JUMP, label);
|
||||||
|
emit->suppress = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
@ -766,6 +786,7 @@ void mp_emit_bc_call_method(emit_t *emit, mp_uint_t n_positional, mp_uint_t n_ke
|
|||||||
|
|
||||||
void mp_emit_bc_return_value(emit_t *emit) {
|
void mp_emit_bc_return_value(emit_t *emit) {
|
||||||
emit_write_bytecode_byte(emit, -1, MP_BC_RETURN_VALUE);
|
emit_write_bytecode_byte(emit, -1, MP_BC_RETURN_VALUE);
|
||||||
|
emit->suppress = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mp_emit_bc_raise_varargs(emit_t *emit, mp_uint_t n_args) {
|
void mp_emit_bc_raise_varargs(emit_t *emit, mp_uint_t n_args) {
|
||||||
@ -773,6 +794,7 @@ void mp_emit_bc_raise_varargs(emit_t *emit, mp_uint_t n_args) {
|
|||||||
MP_STATIC_ASSERT(MP_BC_RAISE_LAST + 2 == MP_BC_RAISE_FROM);
|
MP_STATIC_ASSERT(MP_BC_RAISE_LAST + 2 == MP_BC_RAISE_FROM);
|
||||||
assert(n_args <= 2);
|
assert(n_args <= 2);
|
||||||
emit_write_bytecode_byte(emit, -n_args, MP_BC_RAISE_LAST + n_args);
|
emit_write_bytecode_byte(emit, -n_args, MP_BC_RAISE_LAST + n_args);
|
||||||
|
emit->suppress = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mp_emit_bc_yield(emit_t *emit, int kind) {
|
void mp_emit_bc_yield(emit_t *emit, int kind) {
|
||||||
|
@ -1966,6 +1966,7 @@ STATIC void emit_native_jump(emit_t *emit, mp_uint_t label) {
|
|||||||
need_stack_settled(emit);
|
need_stack_settled(emit);
|
||||||
ASM_JUMP(emit->as, label);
|
ASM_JUMP(emit->as, label);
|
||||||
emit_post(emit);
|
emit_post(emit);
|
||||||
|
mp_asm_base_suppress_code(&emit->as->base);
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC void emit_native_jump_helper(emit_t *emit, bool cond, mp_uint_t label, bool pop) {
|
STATIC void emit_native_jump_helper(emit_t *emit, bool cond, mp_uint_t label, bool pop) {
|
||||||
@ -2810,6 +2811,7 @@ STATIC void emit_native_raise_varargs(emit_t *emit, mp_uint_t n_args) {
|
|||||||
}
|
}
|
||||||
// TODO probably make this 1 call to the runtime (which could even call convert, native_raise(obj, type))
|
// TODO probably make this 1 call to the runtime (which could even call convert, native_raise(obj, type))
|
||||||
emit_call(emit, MP_F_NATIVE_RAISE);
|
emit_call(emit, MP_F_NATIVE_RAISE);
|
||||||
|
mp_asm_base_suppress_code(&emit->as->base);
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC void emit_native_yield(emit_t *emit, int kind) {
|
STATIC void emit_native_yield(emit_t *emit, int kind) {
|
||||||
|
@ -119,12 +119,12 @@ def f():
|
|||||||
#from sys import * # tested at module scope
|
#from sys import * # tested at module scope
|
||||||
|
|
||||||
# raise
|
# raise
|
||||||
raise
|
if a: raise
|
||||||
raise 1
|
if a: raise 1
|
||||||
|
|
||||||
# return
|
# return
|
||||||
return
|
if a: return
|
||||||
return 1
|
if a: return 1
|
||||||
|
|
||||||
# function with lots of locals
|
# function with lots of locals
|
||||||
def f():
|
def f():
|
||||||
|
@ -47,8 +47,8 @@ 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 @\.\+ 45\[46\] bytes)
|
File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ 46\[68\] bytes)
|
||||||
Raw bytecode (code_info_size=8\[46\], bytecode_size=372):
|
Raw bytecode (code_info_size=8\[46\], bytecode_size=382):
|
||||||
a8 12 9\[bf\] 03 05 60 60 26 22 24 64 22 24 25 25 24
|
a8 12 9\[bf\] 03 05 60 60 26 22 24 64 22 24 25 25 24
|
||||||
26 23 63 22 22 25 23 23 2f 6c 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
|
||||||
@ -126,19 +126,18 @@ arg names:
|
|||||||
bc=313 line=100
|
bc=313 line=100
|
||||||
bc=315 line=101
|
bc=315 line=101
|
||||||
########
|
########
|
||||||
bc=321 line=103
|
bc=325 line=106
|
||||||
bc=327 line=106
|
bc=329 line=107
|
||||||
bc=331 line=107
|
bc=335 line=110
|
||||||
bc=337 line=110
|
bc=338 line=111
|
||||||
bc=340 line=111
|
bc=344 line=114
|
||||||
bc=346 line=114
|
bc=344 line=117
|
||||||
bc=346 line=117
|
bc=349 line=118
|
||||||
bc=351 line=118
|
bc=361 line=121
|
||||||
bc=363 line=121
|
bc=361 line=122
|
||||||
bc=363 line=122
|
bc=365 line=123
|
||||||
bc=364 line=123
|
bc=370 line=126
|
||||||
bc=366 line=126
|
bc=375 line=127
|
||||||
bc=368 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__
|
||||||
@ -363,48 +362,55 @@ arg names:
|
|||||||
308 LOAD_FAST 1
|
308 LOAD_FAST 1
|
||||||
309 POP_TOP
|
309 POP_TOP
|
||||||
310 END_FINALLY
|
310 END_FINALLY
|
||||||
311 JUMP 324
|
311 JUMP 322
|
||||||
313 SETUP_EXCEPT 320
|
313 SETUP_EXCEPT 318
|
||||||
315 UNWIND_JUMP 327 1
|
315 UNWIND_JUMP 325 1
|
||||||
318 POP_EXCEPT_JUMP 324
|
318 POP_TOP
|
||||||
320 POP_TOP
|
319 POP_EXCEPT_JUMP 322
|
||||||
321 POP_EXCEPT_JUMP 324
|
321 END_FINALLY
|
||||||
323 END_FINALLY
|
322 LOAD_FAST 0
|
||||||
324 LOAD_FAST 0
|
323 POP_JUMP_IF_TRUE 313
|
||||||
325 POP_JUMP_IF_TRUE 313
|
325 LOAD_FAST 0
|
||||||
327 LOAD_FAST 0
|
326 SETUP_WITH 333
|
||||||
328 SETUP_WITH 335
|
328 POP_TOP
|
||||||
330 POP_TOP
|
329 LOAD_DEREF 14
|
||||||
331 LOAD_DEREF 14
|
331 POP_TOP
|
||||||
333 POP_TOP
|
332 LOAD_CONST_NONE
|
||||||
334 LOAD_CONST_NONE
|
333 WITH_CLEANUP
|
||||||
335 WITH_CLEANUP
|
334 END_FINALLY
|
||||||
336 END_FINALLY
|
335 LOAD_CONST_SMALL_INT 1
|
||||||
337 LOAD_CONST_SMALL_INT 1
|
336 STORE_DEREF 16
|
||||||
338 STORE_DEREF 16
|
338 LOAD_FAST_N 16
|
||||||
340 LOAD_FAST_N 16
|
340 MAKE_CLOSURE \.\+ 1
|
||||||
342 MAKE_CLOSURE \.\+ 1
|
343 STORE_FAST 13
|
||||||
345 STORE_FAST 13
|
344 LOAD_CONST_SMALL_INT 0
|
||||||
346 LOAD_CONST_SMALL_INT 0
|
345 LOAD_CONST_NONE
|
||||||
347 LOAD_CONST_NONE
|
346 IMPORT_NAME 'a'
|
||||||
348 IMPORT_NAME 'a'
|
348 STORE_FAST 0
|
||||||
350 STORE_FAST 0
|
349 LOAD_CONST_SMALL_INT 0
|
||||||
351 LOAD_CONST_SMALL_INT 0
|
350 LOAD_CONST_STRING 'b'
|
||||||
352 LOAD_CONST_STRING 'b'
|
352 BUILD_TUPLE 1
|
||||||
354 BUILD_TUPLE 1
|
354 IMPORT_NAME 'a'
|
||||||
356 IMPORT_NAME 'a'
|
356 IMPORT_FROM 'b'
|
||||||
358 IMPORT_FROM 'b'
|
358 STORE_DEREF 14
|
||||||
360 STORE_DEREF 14
|
360 POP_TOP
|
||||||
362 POP_TOP
|
361 LOAD_FAST 0
|
||||||
363 RAISE_LAST
|
362 POP_JUMP_IF_FALSE 365
|
||||||
364 LOAD_CONST_SMALL_INT 1
|
364 RAISE_LAST
|
||||||
365 RAISE_OBJ
|
365 LOAD_FAST 0
|
||||||
366 LOAD_CONST_NONE
|
366 POP_JUMP_IF_FALSE 370
|
||||||
367 RETURN_VALUE
|
|
||||||
368 LOAD_CONST_SMALL_INT 1
|
368 LOAD_CONST_SMALL_INT 1
|
||||||
369 RETURN_VALUE
|
369 RAISE_OBJ
|
||||||
370 LOAD_CONST_NONE
|
370 LOAD_FAST 0
|
||||||
371 RETURN_VALUE
|
371 POP_JUMP_IF_FALSE 375
|
||||||
|
373 LOAD_CONST_NONE
|
||||||
|
374 RETURN_VALUE
|
||||||
|
375 LOAD_FAST 0
|
||||||
|
376 POP_JUMP_IF_FALSE 380
|
||||||
|
378 LOAD_CONST_SMALL_INT 1
|
||||||
|
379 RETURN_VALUE
|
||||||
|
380 LOAD_CONST_NONE
|
||||||
|
381 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 05 80 82 34 38 81 57 c0 57 c1 57 c2 57
|
a8 10 0a 05 80 82 34 38 81 57 c0 57 c1 57 c2 57
|
||||||
@ -623,9 +629,9 @@ arg names: *
|
|||||||
08 DELETE_DEREF 0
|
08 DELETE_DEREF 0
|
||||||
10 LOAD_CONST_NONE
|
10 LOAD_CONST_NONE
|
||||||
11 RETURN_VALUE
|
11 RETURN_VALUE
|
||||||
File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ 15 bytes)
|
File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ 13 bytes)
|
||||||
Raw bytecode (code_info_size=8, bytecode_size=7):
|
Raw bytecode (code_info_size=8, bytecode_size=5):
|
||||||
9a 01 0a 05 03 08 80 8b b1 25 00 f2 63 51 63
|
9a 01 0a 05 03 08 80 8b b1 25 00 f2 63
|
||||||
arg names: * b
|
arg names: * b
|
||||||
(N_STATE 4)
|
(N_STATE 4)
|
||||||
(N_EXC_STACK 0)
|
(N_EXC_STACK 0)
|
||||||
@ -635,8 +641,6 @@ arg names: * b
|
|||||||
01 LOAD_DEREF 0
|
01 LOAD_DEREF 0
|
||||||
03 BINARY_OP 27 __add__
|
03 BINARY_OP 27 __add__
|
||||||
04 RETURN_VALUE
|
04 RETURN_VALUE
|
||||||
05 LOAD_CONST_NONE
|
|
||||||
06 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\+
|
||||||
|
33
tests/cmdline/cmd_showbc_opt.py
Normal file
33
tests/cmdline/cmd_showbc_opt.py
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# cmdline: -v -v
|
||||||
|
# test printing of bytecode when it's optimised away
|
||||||
|
|
||||||
|
|
||||||
|
def f0():
|
||||||
|
return 0
|
||||||
|
print(1)
|
||||||
|
|
||||||
|
|
||||||
|
def f1(x):
|
||||||
|
if x:
|
||||||
|
return
|
||||||
|
print(1)
|
||||||
|
print(2)
|
||||||
|
|
||||||
|
|
||||||
|
def f2(x):
|
||||||
|
raise Exception
|
||||||
|
print(1)
|
||||||
|
|
||||||
|
|
||||||
|
def f3(x):
|
||||||
|
while x:
|
||||||
|
break
|
||||||
|
print(1)
|
||||||
|
print(2)
|
||||||
|
|
||||||
|
|
||||||
|
def f4(x):
|
||||||
|
while x:
|
||||||
|
continue
|
||||||
|
print(1)
|
||||||
|
print(2)
|
122
tests/cmdline/cmd_showbc_opt.py.exp
Normal file
122
tests/cmdline/cmd_showbc_opt.py.exp
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
File cmdline/cmd_showbc_opt.py, code block '<module>' (descriptor: \.\+, bytecode @\.\+ 35 bytes)
|
||||||
|
Raw bytecode (code_info_size=13, bytecode_size=22):
|
||||||
|
00 16 01 60 20 64 40 84 07 64 40 84 07 32 00 16
|
||||||
|
02 32 01 16 03 32 02 16 04 32 03 16 05 32 04 16
|
||||||
|
06 51 63
|
||||||
|
arg names:
|
||||||
|
(N_STATE 1)
|
||||||
|
(N_EXC_STACK 0)
|
||||||
|
bc=0 line=1
|
||||||
|
bc=0 line=4
|
||||||
|
bc=0 line=5
|
||||||
|
bc=4 line=8
|
||||||
|
bc=4 line=10
|
||||||
|
bc=8 line=17
|
||||||
|
bc=12 line=20
|
||||||
|
bc=12 line=22
|
||||||
|
bc=16 line=29
|
||||||
|
00 MAKE_FUNCTION \.\+
|
||||||
|
02 STORE_NAME f0
|
||||||
|
04 MAKE_FUNCTION \.\+
|
||||||
|
06 STORE_NAME f1
|
||||||
|
08 MAKE_FUNCTION \.\+
|
||||||
|
10 STORE_NAME f2
|
||||||
|
12 MAKE_FUNCTION \.\+
|
||||||
|
14 STORE_NAME f3
|
||||||
|
16 MAKE_FUNCTION \.\+
|
||||||
|
18 STORE_NAME f4
|
||||||
|
20 LOAD_CONST_NONE
|
||||||
|
21 RETURN_VALUE
|
||||||
|
File cmdline/cmd_showbc_opt.py, code block 'f0' (descriptor: \.\+, bytecode @\.\+ 8 bytes)
|
||||||
|
Raw bytecode (code_info_size=6, bytecode_size=2):
|
||||||
|
08 08 02 60 40 22 80 63
|
||||||
|
arg names:
|
||||||
|
(N_STATE 2)
|
||||||
|
(N_EXC_STACK 0)
|
||||||
|
bc=0 line=1
|
||||||
|
bc=0 line=4
|
||||||
|
bc=0 line=6
|
||||||
|
bc=2 line=7
|
||||||
|
00 LOAD_CONST_SMALL_INT 0
|
||||||
|
01 RETURN_VALUE
|
||||||
|
File cmdline/cmd_showbc_opt.py, code block 'f1' (descriptor: \.\+, bytecode @\.\+ 22 bytes)
|
||||||
|
Raw bytecode (code_info_size=9, bytecode_size=13):
|
||||||
|
11 0e 03 08 80 0a 23 22 20 b0 44 42 51 63 12 07
|
||||||
|
82 34 01 59 51 63
|
||||||
|
arg names: x
|
||||||
|
(N_STATE 3)
|
||||||
|
(N_EXC_STACK 0)
|
||||||
|
bc=0 line=1
|
||||||
|
bc=0 line=11
|
||||||
|
bc=3 line=12
|
||||||
|
bc=5 line=13
|
||||||
|
bc=5 line=14
|
||||||
|
00 LOAD_FAST 0
|
||||||
|
01 POP_JUMP_IF_FALSE 5
|
||||||
|
03 LOAD_CONST_NONE
|
||||||
|
04 RETURN_VALUE
|
||||||
|
05 LOAD_GLOBAL print
|
||||||
|
07 LOAD_CONST_SMALL_INT 2
|
||||||
|
08 CALL_FUNCTION n=1 nkw=0
|
||||||
|
10 POP_TOP
|
||||||
|
11 LOAD_CONST_NONE
|
||||||
|
12 RETURN_VALUE
|
||||||
|
File cmdline/cmd_showbc_opt.py, code block 'f2' (descriptor: \.\+, bytecode @\.\+ 10 bytes)
|
||||||
|
Raw bytecode (code_info_size=7, bytecode_size=3):
|
||||||
|
11 0a 04 08 80 11 23 12 09 65
|
||||||
|
arg names: x
|
||||||
|
(N_STATE 3)
|
||||||
|
(N_EXC_STACK 0)
|
||||||
|
bc=0 line=1
|
||||||
|
bc=0 line=18
|
||||||
|
bc=3 line=19
|
||||||
|
00 LOAD_GLOBAL Exception
|
||||||
|
02 RAISE_OBJ
|
||||||
|
File cmdline/cmd_showbc_opt.py, code block 'f3' (descriptor: \.\+, bytecode @\.\+ 24 bytes)
|
||||||
|
Raw bytecode (code_info_size=9, bytecode_size=15):
|
||||||
|
11 0e 05 08 80 16 22 22 23 42 42 42 43 b0 43 3b
|
||||||
|
12 07 82 34 01 59 51 63
|
||||||
|
arg names: x
|
||||||
|
(N_STATE 3)
|
||||||
|
(N_EXC_STACK 0)
|
||||||
|
bc=0 line=1
|
||||||
|
bc=0 line=23
|
||||||
|
bc=2 line=24
|
||||||
|
bc=4 line=25
|
||||||
|
bc=7 line=26
|
||||||
|
00 JUMP 4
|
||||||
|
02 JUMP 7
|
||||||
|
04 LOAD_FAST 0
|
||||||
|
05 POP_JUMP_IF_TRUE 2
|
||||||
|
07 LOAD_GLOBAL print
|
||||||
|
09 LOAD_CONST_SMALL_INT 2
|
||||||
|
10 CALL_FUNCTION n=1 nkw=0
|
||||||
|
12 POP_TOP
|
||||||
|
13 LOAD_CONST_NONE
|
||||||
|
14 RETURN_VALUE
|
||||||
|
File cmdline/cmd_showbc_opt.py, code block 'f4' (descriptor: \.\+, bytecode @\.\+ 24 bytes)
|
||||||
|
Raw bytecode (code_info_size=9, bytecode_size=15):
|
||||||
|
11 0e 06 08 80 1d 22 22 23 42 42 42 40 b0 43 3b
|
||||||
|
12 07 82 34 01 59 51 63
|
||||||
|
arg names: x
|
||||||
|
(N_STATE 3)
|
||||||
|
(N_EXC_STACK 0)
|
||||||
|
bc=0 line=1
|
||||||
|
bc=0 line=30
|
||||||
|
bc=2 line=31
|
||||||
|
bc=4 line=32
|
||||||
|
bc=7 line=33
|
||||||
|
00 JUMP 4
|
||||||
|
02 JUMP 4
|
||||||
|
04 LOAD_FAST 0
|
||||||
|
05 POP_JUMP_IF_TRUE 2
|
||||||
|
07 LOAD_GLOBAL print
|
||||||
|
09 LOAD_CONST_SMALL_INT 2
|
||||||
|
10 CALL_FUNCTION n=1 nkw=0
|
||||||
|
12 POP_TOP
|
||||||
|
13 LOAD_CONST_NONE
|
||||||
|
14 RETURN_VALUE
|
||||||
|
mem: total=\\d\+, current=\\d\+, peak=\\d\+
|
||||||
|
stack: \\d\+ out of \\d\+
|
||||||
|
GC: total: \\d\+, used: \\d\+, free: \\d\+
|
||||||
|
No. of 1-blocks: \\d\+, 2-blocks: \\d\+, max blk sz: \\d\+, max free sz: \\d\+
|
Loading…
Reference in New Issue
Block a user