summaryrefslogtreecommitdiffstats
path: root/vm.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2018-03-29 20:24:40 -0700
committerKaz Kylheku <kaz@kylheku.com>2018-03-29 20:24:40 -0700
commit0b6e2afdf3658b2fb4ca786d9d62a67b09894684 (patch)
treede3d6f6b341515f1f99ff4078d28f857b653d70c /vm.c
parent2de8ca1202b448f10f29e5e814252ed3a9003148 (diff)
downloadtxr-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.c1
1 files changed, 1 insertions, 0 deletions
diff --git a/vm.c b/vm.c
index e5489c2c..4d041fce 100644
--- a/vm.c
+++ b/vm.c
@@ -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;