Merge pull request #8071 from tannewt/cpx_stack_size
Slim down stack frames
This commit is contained in:
commit
b71f394127
@ -59,8 +59,8 @@ extern void common_hal_mcu_enable_interrupts(void);
|
|||||||
//
|
//
|
||||||
// default is 128; consider raising to reduce fragmentation.
|
// default is 128; consider raising to reduce fragmentation.
|
||||||
#define MICROPY_ALLOC_PARSE_CHUNK_INIT (16)
|
#define MICROPY_ALLOC_PARSE_CHUNK_INIT (16)
|
||||||
// default is 512.
|
// default is 512. Longest path in .py bundle as of June 6th, 2023 is 73 characters.
|
||||||
#define MICROPY_ALLOC_PATH_MAX (256)
|
#define MICROPY_ALLOC_PATH_MAX (96)
|
||||||
#define MICROPY_CAN_OVERRIDE_BUILTINS (1)
|
#define MICROPY_CAN_OVERRIDE_BUILTINS (1)
|
||||||
#define MICROPY_COMP_CONST (1)
|
#define MICROPY_COMP_CONST (1)
|
||||||
#define MICROPY_COMP_DOUBLE_TUPLE_ASSIGN (1)
|
#define MICROPY_COMP_DOUBLE_TUPLE_ASSIGN (1)
|
||||||
|
10
py/runtime.c
10
py/runtime.c
@ -201,7 +201,7 @@ mp_obj_t MICROPY_WRAP_MP_LOAD_GLOBAL(mp_load_global)(qstr qst) {
|
|||||||
return elem->value;
|
return elem->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
mp_obj_t mp_load_build_class(void) {
|
mp_obj_t __attribute__((noinline)) mp_load_build_class(void) {
|
||||||
DEBUG_OP_printf("load_build_class\n");
|
DEBUG_OP_printf("load_build_class\n");
|
||||||
#if MICROPY_CAN_OVERRIDE_BUILTINS
|
#if MICROPY_CAN_OVERRIDE_BUILTINS
|
||||||
if (MP_STATE_VM(mp_module_builtins_override_dict) != NULL) {
|
if (MP_STATE_VM(mp_module_builtins_override_dict) != NULL) {
|
||||||
@ -858,7 +858,7 @@ mp_obj_t mp_call_method_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_ob
|
|||||||
}
|
}
|
||||||
|
|
||||||
// unpacked items are stored in reverse order into the array pointed to by items
|
// unpacked items are stored in reverse order into the array pointed to by items
|
||||||
void mp_unpack_sequence(mp_obj_t seq_in, size_t num, mp_obj_t *items) {
|
void __attribute__((noinline,)) mp_unpack_sequence(mp_obj_t seq_in, size_t num, mp_obj_t *items) {
|
||||||
size_t seq_len;
|
size_t seq_len;
|
||||||
if (mp_obj_is_type(seq_in, &mp_type_tuple) || mp_obj_is_type(seq_in, &mp_type_list)) {
|
if (mp_obj_is_type(seq_in, &mp_type_tuple) || mp_obj_is_type(seq_in, &mp_type_list)) {
|
||||||
mp_obj_t *seq_items;
|
mp_obj_t *seq_items;
|
||||||
@ -905,7 +905,7 @@ too_long:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// unpacked items are stored in reverse order into the array pointed to by items
|
// unpacked items are stored in reverse order into the array pointed to by items
|
||||||
void mp_unpack_ex(mp_obj_t seq_in, size_t num_in, mp_obj_t *items) {
|
void __attribute__((noinline)) mp_unpack_ex(mp_obj_t seq_in, size_t num_in, mp_obj_t *items) {
|
||||||
size_t num_left = num_in & 0xff;
|
size_t num_left = num_in & 0xff;
|
||||||
size_t num_right = (num_in >> 8) & 0xff;
|
size_t num_right = (num_in >> 8) & 0xff;
|
||||||
DEBUG_OP_printf("unpack ex " UINT_FMT " " UINT_FMT "\n", num_left, num_right);
|
DEBUG_OP_printf("unpack ex " UINT_FMT " " UINT_FMT "\n", num_left, num_right);
|
||||||
@ -1482,7 +1482,7 @@ mp_obj_t mp_import_name(qstr name, mp_obj_t fromlist, mp_obj_t level) {
|
|||||||
return mp_builtin___import__(5, args);
|
return mp_builtin___import__(5, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
mp_obj_t mp_import_from(mp_obj_t module, qstr name) {
|
mp_obj_t __attribute__((noinline,)) mp_import_from(mp_obj_t module, qstr name) {
|
||||||
DEBUG_printf("import from %p %s\n", module, qstr_str(name));
|
DEBUG_printf("import from %p %s\n", module, qstr_str(name));
|
||||||
|
|
||||||
mp_obj_t dest[2];
|
mp_obj_t dest[2];
|
||||||
@ -1528,7 +1528,7 @@ mp_obj_t mp_import_from(mp_obj_t module, qstr name) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void mp_import_all(mp_obj_t module) {
|
void __attribute__((noinline)) mp_import_all(mp_obj_t module) {
|
||||||
DEBUG_printf("import all %p\n", module);
|
DEBUG_printf("import all %p\n", module);
|
||||||
|
|
||||||
// TODO: Support __all__
|
// TODO: Support __all__
|
||||||
|
64
tools/gdb-stack-size.py
Normal file
64
tools/gdb-stack-size.py
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
"""Source this file into gdb `source ../../tools/gdb-stack-size.py` then run
|
||||||
|
`stack-size` to print a backtrace with each frame size next to it."""
|
||||||
|
|
||||||
|
|
||||||
|
class StackSize(gdb.Command):
|
||||||
|
def __init__(self):
|
||||||
|
super(StackSize, self).__init__("stack-size", gdb.COMMAND_USER)
|
||||||
|
|
||||||
|
def invoke(self, arg, from_tty):
|
||||||
|
frame = gdb.newest_frame()
|
||||||
|
total_size = 0
|
||||||
|
while frame:
|
||||||
|
sp = frame.read_register("sp")
|
||||||
|
frame_up = frame.older()
|
||||||
|
if not frame_up:
|
||||||
|
break
|
||||||
|
f = frame.function()
|
||||||
|
l = frame.level()
|
||||||
|
if l < 10:
|
||||||
|
l = "#" + str(l) + " "
|
||||||
|
else:
|
||||||
|
l = "#" + str(l)
|
||||||
|
size = frame_up.read_register("sp") - sp
|
||||||
|
total_size += size
|
||||||
|
print(l, sp, frame.type(), f, " " * (40 - len(str(f))), size)
|
||||||
|
# print(dir(f))
|
||||||
|
# Tweak this if for more detail for a specific function.
|
||||||
|
if False and f.name == "mp_execute_bytecode":
|
||||||
|
b = frame.block()
|
||||||
|
prev_b = None
|
||||||
|
while not b.is_static:
|
||||||
|
print(" block", hex(b.start), hex(b.end), b.function)
|
||||||
|
for sym in b:
|
||||||
|
if not sym.needs_frame:
|
||||||
|
continue
|
||||||
|
v = sym.value(frame)
|
||||||
|
print(" ", sym.addr_class, v.address, sym.type.sizeof, sym, sym.type, v)
|
||||||
|
prev_b = b
|
||||||
|
b = b.superblock
|
||||||
|
|
||||||
|
if b.function == f:
|
||||||
|
break
|
||||||
|
b = prev_b
|
||||||
|
print("pc scan", hex(b.start), hex(b.end))
|
||||||
|
seen = set()
|
||||||
|
for pc in range(b.start, b.end, 2):
|
||||||
|
b = gdb.block_for_pc(pc)
|
||||||
|
r = (b.start, b.end)
|
||||||
|
if r in seen:
|
||||||
|
continue
|
||||||
|
seen.add(r)
|
||||||
|
print(" ", hex(pc), hex(b.start), hex(b.end), b.function)
|
||||||
|
for sym in b:
|
||||||
|
if not sym.needs_frame:
|
||||||
|
continue
|
||||||
|
# if sym.type.sizeof <= 4:
|
||||||
|
# continue
|
||||||
|
v = sym.value(frame)
|
||||||
|
print(" ", sym.addr_class, v.address, sym.type.sizeof, sym, sym.type, v)
|
||||||
|
frame = frame_up
|
||||||
|
print("total size:", total_size)
|
||||||
|
|
||||||
|
|
||||||
|
StackSize()
|
28
tools/stack-loc-to-pc.py
Normal file
28
tools/stack-loc-to-pc.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
"""Prints the pcs that access each stack location in a function. Useful for finding
|
||||||
|
infrequently used stack space.
|
||||||
|
|
||||||
|
Pipe in disassembly like so:
|
||||||
|
|
||||||
|
arm-none-eabi-objdump --disassemble=mp_execute_bytecode build-metro_m0_express/firmware.elf | python ../../tools/stack-loc-to-pc.py
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import re
|
||||||
|
|
||||||
|
offset = re.compile(r"sp, #(\d+)")
|
||||||
|
|
||||||
|
offsets = {}
|
||||||
|
for line in sys.stdin:
|
||||||
|
if "sp" in line:
|
||||||
|
m = offset.search(line)
|
||||||
|
o = int(m.groups()[0])
|
||||||
|
pc = line.split(":")[0]
|
||||||
|
if o not in offsets:
|
||||||
|
offsets[o] = []
|
||||||
|
offsets[o].append(pc.strip())
|
||||||
|
|
||||||
|
print("Offset", "Size", "PCs", sep="\t")
|
||||||
|
last_o = 0
|
||||||
|
for o in sorted(offsets):
|
||||||
|
print(o, o - last_o, offsets[o], sep="\t")
|
||||||
|
last_o = o
|
Loading…
Reference in New Issue
Block a user