2 ms·
Okay, here's the very recent problem I had to solve. There is a huge dump of a VM heap, represented as a key-value map: the values are either simple atomic valu
by Joker_vD 5y ago
Okay, here's the very recent problem I had to solve. There is a huge dump of a VM heap, represented as a key-value map: the values are either simple atomic values or compound structures that have addresses (keys into this map) as their parts. There is a list of "entry points" into the heap: addresses of the GC roots in the heap. The problem is to reconstruct the values stored in the heap. E.g., reconstructing starting from "heap(10)" in this heap:
heap(10): cons(int(1),heap(18))
heap(18): cons(int(2),heap(20))
heap(20): cons(int(3),nil)
should result in
[1, 2, 3]
Here's the thing: recursive walk is totally straightforward:
def restore(v):
if v.kind...
elif v.kind == 'tuple':
return Tuple([restore(v[i]) for i in range(v.arity)])
elif v.kind == 'cons':
return List(restore(v[0]), restore(v[1]))
elif v.kind...
else:
return UnknownValue()
But since Python has a limit of 1000 nested function calls, restoration of long lists fails with StackOverflow, and so I had to rewrite it using manual stack. The result is sort of ugly, in fact, I had to use two stacks: one for temporary reconstructed pieces of data, one for "what to do next". Essentially it's implementing a variation of the shunting yard algorithm and while the resulting code is kinda clear in intent, it's still three times as long as the recursive version and is not obviously correct. In fact, I had to tweak it several times (including the introduction of the second stack) before I stopped seeing some (not all!) lists reconstructed in the reverse order.