VM Backtraces
We would like to support good backtraces for bytecode functions. This means that the existing backtrace machinery for native code needs to be extended so it can also handle bytecode functions.
The idea we've come with to support this is to make VM frames work a little more like native frames, by pushing the IP to the VM stack just before a call. The caller does not actually need this address to return, like you would natively, but its presence on the stack can be used to get the chain of function calls and make a backtrace.
In order to present any useful information we would also need DWARF-like line tables (#1449).
To reconstruct a backtrace, we would follow these steps:
- Get a system backtrace containing return PC addresses using the C
backtrace(void **buffer, int size)function. - We get a VM backtrace containing return IP values using our own
backtrace_vmfunction. To achieve this, we will have to push/pop the IP withinbytecode_vmevery time we call from the VM. We must also maintain a linked list of VM frame pointers on the VM stack. - We search for return PC addresses that fall within the
bytecode_vmfunction executable code. - For each
bytecode_vmreturn PC address, we look in the VM stack for the corresponding IP value. There needs to be a one-to-one correspondence betweenbytecode_vmPC addresses and IP addresses. This will be violated if an error occurs when we are within thebytecode_vmfunction. If we could get retain perfect debug information of the IP register within thebytecode_vmfunction we could recover the IP wherever we are within thebytecode_vmfunction.
With an IP backtrace, we can use DWARF-like line tables that our bytecode compiler will generate to convert IP addresses to source information. When our bytecode compiler generates these line tables along with the bytecode modules, it will register the bytecode line tables with clasp's runtime just like we register object files generated by llvm.