8000 Merge pull request #1515 from tannewt/fix_long_live · tannewt/circuitpython@3d07571 · GitHub
[go: up one dir, main page]

Skip to content

Commit 3d07571

Browse files
authored
Merge pull request micropython#1515 from tannewt/fix_long_live
Fix a couple long live issues
2 parents 12917d3 + 5555a24 commit 3d07571

File tree

3 files changed

+52
-10
lines changed

3 files changed

+52
-10
lines changed

py/gc_long_lived.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "py/emitglue.h"
2828
#include "py/gc_long_lived.h"
2929
#include "py/gc.h"
30+
#include "py/mpstate.h"
3031

3132
mp_obj_fun_bc_t *make_fun_bc_long_lived(mp_obj_fun_bc_t *fun_bc, uint8_t max_depth) {
3233
#ifndef MICROPY_ENABLE_GC
@@ -88,7 +89,7 @@ mp_obj_dict_t *make_dict_long_lived(mp_obj_dict_t *dict, uint8_t max_depth) {
8889
#ifndef MICROPY_ENABLE_GC
8990
return dict;
9091
#endif
91-
if (dict == NULL || max_depth == 0) {
92+
if (dict == NULL || max_depth == 0 || dict == &MP_STATE_VM(dict_main)) {
9293
return dict;
9394
}
9495
// Don't recurse unnecessarily. Return immediately if we've already seen this dict.

py/objtype.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1065,7 +1065,7 @@ STATIC void type_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
10651065

10661066
// store attribute
10671067
mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
1068-
elem->value = make_obj_long_lived(dest[1], 10);
1068+
elem->value = dest[1];
10691069
dest[0] = MP_OBJ_NULL; // indicate success
10701070
}
10711071
}

tools/analyze_heap_dump.py

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -162,24 +162,50 @@ def load(address, size=4):
162162
def load_pointer(address):
163163
return struct.unpack("<I", load(address))[0]
164164

165-
heap_start, heap_size = symbols["heap"]
165+
if "heap" in symbols:
166+
heap_start, heap_size = symbols["heap"]
167+
else:
168+
print("no static heap")
169+
allocations_start, allocations_size = symbols["allocations"]
170+
allocations = load(allocations_start, allocations_size)
171+
first_zero = True
172+
potential_heap = None
173+
# The heap is the last left hand allocated section that should span all the way to the
174+
# right side list.
175+
for address, size in struct.iter_unpack("<II", allocations):
176+
print(address, size)
177+
if address == 0 and first_zero:
178+
first_zero = False
179+
if first_zero:
180+
potential_heap = (address, size)
181+
182+
if not first_zero and address != 0:
183+
if address != potential_heap[0] + potential_heap[1]:
184+
print("no active heap")
185+
return
186+
else:
187+
heap_start, heap_size = potential_heap
188+
break
189+
print("found heap", heap_start, heap_size)
166190
heap = load(heap_start, heap_size)
167191
total_byte_len = len(heap)
168192

169193
# These change every run so we load them from the symbol table
170194
mp_state_ctx = symbols["mp_state_ctx"][0]
171195
manual_symbol_map["mp_state_ctx+20"] = "mp_state_ctx.vm.last_pool"
172196
last_pool = load_pointer(mp_state_ctx + 20) # (gdb) p &mp_state_ctx.vm.last_pool
173-
manual_symbol_map["mp_state_ctx+104"] = "mp_state_ctx.vm.dict_main.map.table"
174-
dict_main_table = load_pointer(mp_state_ctx + 104) # (gdb) p &mp_state_ctx.vm.dict_main.map.table
197+
manual_symbol_map["mp_state_ctx+108"] = "mp_state_ctx.vm.dict_main.map.table"
198+
dict_main_table = load_pointer(mp_state_ctx + 108) # (gdb) p &mp_state_ctx.vm.dict_main.map.table
175199
manual_symbol_map["mp_state_ctx+84"] = "mp_state_ctx.vm.mp_loaded_modules_dict.map.table"
176200
imports_table = load_pointer(mp_state_ctx + 84) # (gdb) p &mp_state_ctx.vm.mp_loaded_modules_dict.map.table
177201

178-
manual_symbol_map["mp_state_ctx+120"] = "mp_state_ctx.vm.mp_sys_path_obj.items"
179-
manual_symbol_map["mp_state_ctx+136"] = "mp_state_ctx.vm.mp_sys_argv_obj.items"
202+
manual_symbol_map["mp_state_ctx+124"] = "mp_state_ctx.vm.mp_sys_path_obj.items"
203+
manual_symbol_map["mp_state_ctx+140"] = "mp_state_ctx.vm.mp_sys_argv_obj.items"
204+
manual_symbol_map["mp_state_ctx+96&quo 6DB6 t;] = "mp_state_ctx.vm.dict_main"
205+
manual_symbol_map["0x200015e0"] = "mp_state_ctx.vm.dict_main"
180206

181207
for i in range(READLINE_HIST_SIZE):
182-
manual_symbol_map["mp_state_ctx+{}".format(144 + i * 4)] = "mp_state_ctx.vm.readline_hist[{}]".format(i)
208+
manual_symbol_map["mp_state_ctx+{}".format(148 + i * 4)] = "mp_state_ctx.vm.readline_hist[{}]".format(i)
183209

184210
tuple_type = symbols["mp_type_tuple"][0]
185211
type_type = symbols["mp_type_type"][0]
@@ -192,6 +218,8 @@ def load_pointer(address):
192218

193219
dynamic_type = 0x40000000 # placeholder, doesn't match any memory
194220

221+
long_lived_start = load_pointer(mp_state_ctx + 272) # (gdb) p &mp_state_ctx.mem.gc_lowest_long_lived_ptr
222+
195223
type_colors = {
196224
dict_type: "red",
197225
property_type: "yellow",
@@ -252,9 +280,14 @@ def save_allocated_block(end, current_allocation):
252280
table = "<<table bgcolor=\"gray\" border=\"1\" cellpadding=\"0\" cellspacing=\"0\"><tr><td colspan=\"4\" port=\"0\" height=\"18\" width=\"80\">0x{:08x}</td></tr>{}</table>>".format(address, rows)
253281

254282
ownership_graph.add_node(address, label=table, style="invisible", shape="plaintext")
283+
print("add 0x{:08x}".format(address))
255284
potential_type = None
256285
node = ownership_graph.get_node(address)
257286
node.attr["height"] = 0.25 * current_allocation
287+
if address >= long_lived_start:
288+
node.attr["fontcolor"] = "hotpink"
289+
else:
290+
node.attr["fontcolor"] = "black"
258291
block_data[address] = data
259292
for k in range(len(data) // 4):
260293
word = struct.unpack_from("<I", data, offset=(k * 4))[0]
@@ -270,6 +303,7 @@ def save_allocated_block(end, current_allocation):
270303
bgcolor = type_colors[potential_type]
271304
elif print_unknown_types:
272305
print("unknown type", hex(potential_type))
306+
273307
node.attr["label"] = "<" + node.attr["label"].replace("\"gray\"", "\"" + bgcolor + "\"") + ">"
274308

275309
if potential_type == str_type and k == 3:
@@ -285,7 +319,7 @@ def save_allocated_block(end, current_allocation):
285319
if k < 4:
286320
port = 0
287321
ownership_graph.add_edge(address, word, tailport=str(port)+":_")
288-
#print(" 0x{:08x}".format(word))
322+
print(" 0x{:08x}".format(word))
289323
if address in qstr_pools:
290324
if k > 0:
291325
qstr_chunks.append(word)
@@ -421,6 +455,7 @@ def format(obj):
421455
node.attr["label"] = "<<table bgcolor=\"gold\" border=\"1\" cellpadding=\"0\" cellspacing=\"0\"><tr><td colspan=\"2\">0x{:08x}</td></tr>{}</table>>".format(block, rows)
422456

423457
for node, degree in ownership_graph.in_degree_iter():
458+
print(node, degree)
424459
if degree == 0:
425460
address_bytes = struct.pack("<I", int(node))
426461
location = -1
@@ -434,6 +469,8 @@ def format(obj):
434469
source = manual_symbol_map[source]
435470
if "readline_hist" in source:
436471
string_blocks.append(int(node))
472+
if pointer_location > heap_start + heap_size:
473+
source = "stack " + source
437474
ownership_graph.add_edge(source, node)
438475

439476
for block in string_blocks:
@@ -517,7 +554,11 @@ def format(obj):
517554
wrapped.append(html.escape(printable_qstrs[i:i+16]))
518555
node = ownership_graph.get_node(block)
519556
node.attr["label"] = "<<table border=\"1\" cellspacing=\"0\" bgcolor=\"lightsalmon\" width=\"80\"><tr><td height=\"18\" >0x{:08x}</td></tr><tr><td height=\"{}\" >{}</td></tr></table>>".format(block, 18 * (len(wrapped) - 1), "<br/>".join(wrapped))
520-
node.attr["fontname"] = "FiraCode-Medium"
557+
node.attr["fontname"] = "FiraCode-Bold"
558+
if block >= long_lived_start:
559+
node.attr["fontcolor"] = "hotpink"
560+
else:
561+
node.attr["fontcolor"] = "black"
521562
node.attr["fontpath"] = "/Users/tannewt/Library/Fonts/"
522563
node.attr["fontsize"] = 8
523564

0 commit comments

Comments
 (0)
0