1
0
mirror of https://github.com/janet-lang/janet synced 2024-07-01 01:23:15 +00:00

Enable debug opcode in vm and debug state for fibers.

This commit is contained in:
Calvin Rose 2018-03-09 17:14:26 -05:00
parent eee453d2c0
commit 0c3b0673ff
7 changed files with 70 additions and 43 deletions

View File

@ -86,6 +86,7 @@ static const DstInstructionDef dst_ops[] = {
{"call", DOP_CALL}, {"call", DOP_CALL},
{"clo", DOP_CLOSURE}, {"clo", DOP_CLOSURE},
{"cmp", DOP_COMPARE}, {"cmp", DOP_COMPARE},
{"debug", DOP_DEBUG},
{"div", DOP_DIVIDE}, {"div", DOP_DIVIDE},
{"divim", DOP_DIVIDE_IMMEDIATE}, {"divim", DOP_DIVIDE_IMMEDIATE},
{"divi", DOP_DIVIDE_INTEGER}, {"divi", DOP_DIVIDE_INTEGER},

View File

@ -85,7 +85,8 @@ enum DstInstructionType dst_instructions[DOP_INSTRUCTION_COUNT] = {
DIT_SSS, /* DOP_PUT, */ DIT_SSS, /* DOP_PUT, */
DIT_SSU, /* DOP_GET_INDEX, */ DIT_SSU, /* DOP_GET_INDEX, */
DIT_SSU, /* DOP_PUT_INDEX, */ DIT_SSU, /* DOP_PUT_INDEX, */
DIT_SS /* DOP_LENGTH */ DIT_SS, /* DOP_LENGTH */
DIT_0 /* DOP_DEBUG */
}; };
/* Verify some bytecode */ /* Verify some bytecode */

View File

@ -192,6 +192,9 @@ int dst_core_fiber_status(DstArgs args) {
case DST_FIBER_ERROR: case DST_FIBER_ERROR:
status = ":error"; status = ":error";
break; break;
case DST_FIBER_DEBUG:
status = ":debug";
break;
} }
return dst_return(args, dst_csymbolv(status)); return dst_return(args, dst_csymbolv(status));
} }

View File

@ -38,6 +38,7 @@ DstFiber *dst_fiber(int32_t capacity) {
} }
fiber->parent = NULL; fiber->parent = NULL;
fiber->maxstack = DST_STACK_MAX; fiber->maxstack = DST_STACK_MAX;
fiber->flags = DST_FIBER_MASK_DEBUG;
return dst_fiber_reset(fiber); return dst_fiber_reset(fiber);
} }

View File

@ -30,19 +30,16 @@ DstFiber *dst_vm_fiber = NULL;
int dst_vm_stackn = 0; int dst_vm_stackn = 0;
/* Helper to ensure proper fiber is activated after returning */ /* Helper to ensure proper fiber is activated after returning */
static int dst_update_fiber() { static int dst_update_fiber(uint32_t mask) {
if (dst_vm_fiber->frame == 0) { if (dst_vm_fiber->frame == 0) {
dst_vm_fiber->status = DST_FIBER_DEAD; dst_vm_fiber->status = DST_FIBER_DEAD;
} }
while (dst_vm_fiber->status == DST_FIBER_DEAD || while (dst_vm_fiber->status == DST_FIBER_DEAD ||
dst_vm_fiber->status == DST_FIBER_ERROR) { dst_vm_fiber->status == DST_FIBER_ERROR ||
dst_vm_fiber->status == DST_FIBER_DEBUG ||
dst_vm_fiber->flags & mask) {
if (NULL != dst_vm_fiber->parent) { if (NULL != dst_vm_fiber->parent) {
dst_vm_fiber = dst_vm_fiber->parent; dst_vm_fiber = dst_vm_fiber->parent;
if (dst_vm_fiber->status == DST_FIBER_ALIVE) {
/* If the parent thread is still alive,
we are inside a cfunction */
return 1;
}
} else { } else {
/* The root thread has terminated */ /* The root thread has terminated */
return 1; return 1;
@ -139,6 +136,7 @@ static void *op_lookup[255] = {
&&label_DOP_GET_INDEX, &&label_DOP_GET_INDEX,
&&label_DOP_PUT_INDEX, &&label_DOP_PUT_INDEX,
&&label_DOP_LENGTH, &&label_DOP_LENGTH,
&&label_DOP_DEBUG,
&&label_unknown_op &&label_unknown_op
}; };
#else #else
@ -204,16 +202,13 @@ static void *op_lookup[255] = {
vm_init_fiber_state(); vm_init_fiber_state();
/* Main interpreter loop. It is large, but it is /* Main interpreter loop. Sematically is a switch on
* is maintainable. Adding new opcodes is mostly just adding newcases * (*pc & 0xFF) inside of an infinte loop. */
* to this loop, adding the opcode to opcodes.h, and adding it to the assembler.
* Some opcodes, especially ones that do arithmetic, are almost entirely
* templated by the above macros. */
VM_START(); VM_START();
VM_DEFAULT(); VM_DEFAULT();
retreg = dst_wrap_string(dst_formatc("unknown opcode %d", *pc & 0xFF)); VM_OP(DOP_DEBUG)
goto vm_error; goto vm_debug;
VM_OP(DOP_NOOP) VM_OP(DOP_NOOP)
pc++; pc++;
@ -707,37 +702,48 @@ static void *op_lookup[255] = {
vm_return_cfunc: vm_return_cfunc:
{ {
dst_fiber_popframe(dst_vm_fiber); dst_fiber_popframe(dst_vm_fiber);
if (dst_update_fiber()) { if (dst_update_fiber(DST_FIBER_MASK_RETURN)) goto vm_exit_value;
*returnreg = retreg;
dst_vm_stackn--;
return 0;
}
stack = dst_vm_fiber->data + dst_vm_fiber->frame; stack = dst_vm_fiber->data + dst_vm_fiber->frame;
stack[oparg(1, 0xFF)] = retreg; stack[oparg(1, 0xFF)] = retreg;
pc++; pc++;
vm_checkgc_next(); vm_checkgc_next();
} }
/* Return from a cfunction that is in tail position (pop 2 stack frames) */
vm_return_cfunc_tail: vm_return_cfunc_tail:
{ {
dst_fiber_popframe(dst_vm_fiber); dst_fiber_popframe(dst_vm_fiber);
if (dst_update_fiber()) { if (dst_update_fiber(DST_FIBER_MASK_RETURN)) goto vm_exit_value;
*returnreg = retreg; goto vm_return;
dst_vm_stackn--;
return 0;
}
/* Fall through to normal return */
} }
/* Handle returning from stack frame. Expect return value in retreg */ /* Handle returning from stack frame. Expect return value in retreg */
vm_return: vm_return:
{ {
dst_fiber_popframe(dst_vm_fiber); dst_fiber_popframe(dst_vm_fiber);
if (dst_update_fiber()) { if (dst_update_fiber(DST_FIBER_MASK_RETURN)) goto vm_exit_value;
*returnreg = retreg; goto vm_reset;
dst_vm_stackn--;
return 0;
} }
/* Handle errors from c functions and vm opcodes */
vm_error:
{
dst_vm_fiber->status = DST_FIBER_ERROR;
if (dst_update_fiber(DST_FIBER_MASK_ERROR)) goto vm_exit_error;
goto vm_reset;
}
/* Handle debugger interrupts */
vm_debug:
{
dst_vm_fiber->status = DST_FIBER_DEBUG;
if (dst_update_fiber(DST_FIBER_MASK_DEBUG)) goto vm_exit_debug;
goto vm_reset;
}
/* Reset state of machine */
vm_reset:
{
stack = dst_vm_fiber->data + dst_vm_fiber->frame; stack = dst_vm_fiber->data + dst_vm_fiber->frame;
func = dst_stack_frame(stack)->func; func = dst_stack_frame(stack)->func;
pc = dst_stack_frame(stack)->pc; pc = dst_stack_frame(stack)->pc;
@ -746,21 +752,28 @@ static void *op_lookup[255] = {
vm_checkgc_next(); vm_checkgc_next();
} }
/* Handle errors from c functions and vm opcodes */ /* Exit loop with return value */
vm_error: vm_exit_value:
{
*returnreg = retreg;
dst_vm_stackn--;
return 0;
}
/* Exit loop with error value */
vm_exit_error:
{ {
dst_vm_fiber->status = DST_FIBER_ERROR;
if (dst_update_fiber()) {
*returnreg = retreg; *returnreg = retreg;
dst_vm_stackn--; dst_vm_stackn--;
return 1; return 1;
} }
stack = dst_vm_fiber->data + dst_vm_fiber->frame;
func = dst_stack_frame(stack)->func; /* Exit loop with debug */
pc = dst_stack_frame(stack)->pc; vm_exit_debug:
stack[oparg(1, 0xFF)] = retreg; {
pc++; *returnreg = dst_wrap_nil();
vm_checkgc_next(); dst_vm_stackn--;
return 2;
} }
VM_END() VM_END()

View File

@ -118,6 +118,7 @@ enum DstOpCode {
DOP_GET_INDEX, DOP_GET_INDEX,
DOP_PUT_INDEX, DOP_PUT_INDEX,
DOP_LENGTH, DOP_LENGTH,
DOP_DEBUG,
DOP_INSTRUCTION_COUNT DOP_INSTRUCTION_COUNT
}; };

View File

@ -305,6 +305,11 @@ struct DstArgs {
Dst *ret; Dst *ret;
}; };
/* Fiber signal masks */
#define DST_FIBER_MASK_RETURN 1
#define DST_FIBER_MASK_ERROR 2
#define DST_FIBER_MASK_DEBUG 4
/* A lightweight green thread in dst. Does not correspond to /* A lightweight green thread in dst. Does not correspond to
* operating system threads. */ * operating system threads. */
struct DstFiber { struct DstFiber {
@ -315,12 +320,14 @@ struct DstFiber {
int32_t stacktop; /* Top of stack. Where values are pushed and popped from. */ int32_t stacktop; /* Top of stack. Where values are pushed and popped from. */
int32_t capacity; int32_t capacity;
int32_t maxstack; /* Arbitrary defined limit for stack overflow */ int32_t maxstack; /* Arbitrary defined limit for stack overflow */
uint32_t flags; /* Various flags */
enum { enum {
DST_FIBER_PENDING, DST_FIBER_PENDING,
DST_FIBER_NEW, DST_FIBER_NEW,
DST_FIBER_ALIVE, DST_FIBER_ALIVE,
DST_FIBER_DEAD, DST_FIBER_DEAD,
DST_FIBER_ERROR DST_FIBER_ERROR,
DST_FIBER_DEBUG
} status; } status;
}; };