diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2018-03-29 20:24:40 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2018-03-29 20:24:40 -0700 |
commit | 0b6e2afdf3658b2fb4ca786d9d62a67b09894684 (patch) | |
tree | de3d6f6b341515f1f99ff4078d28f857b653d70c /vm.c | |
parent | 2de8ca1202b448f10f29e5e814252ed3a9003148 (diff) | |
download | txr-0b6e2afdf3658b2fb4ca786d9d62a67b09894684.tar.gz txr-0b6e2afdf3658b2fb4ca786d9d62a67b09894684.tar.bz2 txr-0b6e2afdf3658b2fb4ca786d9d62a67b09894684.zip |
vm: integrate with delimited continuations.
It doesn't Just Work out of the box. Here is why.
The struct vm state is declared somewhere on the stack,
and then the vm executes various recursive functions.
A block is established by vm_block(). Then if a continuation
is captured up to that block, it will not include that part
of the stack which holds the VM state. When the continuation
is restarted, the struct vm * pointers inside the stack will
be garbage.
The solution: when a continuation is captured to a prompt that
is set up by the VM block instruction (vm_block function),
we put information into the block which says "don't just
capture me plus some slack: please capture the stack all the
way up to this specific address here". That address, of
course, is just past the VM state, ensuring that the VM state
is included in the snapshot.
In short: a delimited continuation terminating in a prompt
set up by the VM just include the entire VM context from the
stack frame where the struct vm on down (i.e. up the stack)
to the capture point.
* unwind.c (uw_push_block): Initialize cont_bottom
member to zero. Interpreted blocks leave this as zero.
Blocks set up by the VM override it.
(revive_cont): Critical: the range check must include
the orig_end endpoint, because when the struct vm is captured
into the continuation it is right at the end of the capture
memory, and the prompt block's cont_bottom member points
exactly to orig_end: one element past the struct vm.
The cont_bottom member must be adjusted by delta
so that continuations captured by the revived VM
inside the continuation get the adjusted cont_bottom at their
current stack location.
(capture_cont): If the block is publishing a non-zer
cont_bottom value, then take that value if it is a higher
address than the lim (including the UW_CONT_FRAME_AFTER
slack).
* unwind.h (struct uw_block): New member, cont_bottom.
By means of this, a block can indicate a higher address
to which a continuation capture can extend.
* vm.c (vm_block): Publish the address one byte past the
virtual machine state as the stack bottom for continuations.
Diffstat (limited to 'vm.c')
-rw-r--r-- | vm.c | 1 |
1 files changed, 1 insertions, 0 deletions
@@ -643,6 +643,7 @@ static void vm_block(struct vm *vm, vm_word_t insn) int saved_lev = vm->lev; uw_block_begin (vm_get(vm->dspl, blname), result); + uw_blk.bl.cont_bottom = coerce(mem_t *, vm + 1); result = vm_execute(vm); uw_block_end; |