1
0
mirror of https://github.com/janet-lang/janet synced 2025-01-13 17:10:27 +00:00

Use computed goto in vm for GCC

This commit is contained in:
bakpakin 2018-01-31 21:40:19 -05:00
parent a6694e985c
commit 1bf0b538cd
2 changed files with 539 additions and 465 deletions

View File

@ -107,7 +107,7 @@ const uint8_t *dst_cstring(const char *str) {
static int32_t real_to_string_impl(uint8_t *buf, double x) { static int32_t real_to_string_impl(uint8_t *buf, double x) {
/* Use 16 decimal places to ignore one ulp errors for now */ /* Use 16 decimal places to ignore one ulp errors for now */
int count = snprintf((char *) buf, DST_BUFSIZE, "%.16g", x); int count = snprintf((char *) buf, DST_BUFSIZE, "%.16gR", x);
return (int32_t) count; return (int32_t) count;
} }

View File

@ -63,9 +63,85 @@ static int dst_continue(Dst *returnreg) {
* Values stored here should be used immediately */ * Values stored here should be used immediately */
Dst retreg; Dst retreg;
/* Eventually use computed gotos for more effient vm loop. */ /* Use computed gotos for GCC, otherwise use switch */
#ifdef __GNUCC__
#define VM_START() {vm_next();
#define VM_END() }
#define VM_OP(op) label_##op :
#define VM_DEFAULT() label_unknown_op:
#define vm_next() goto *op_lookup[*pc & 0xFF];
static void *op_lookup[255] = {
&&label_DOP_NOOP,
&&label_DOP_ERROR,
&&label_DOP_TYPECHECK,
&&label_DOP_RETURN,
&&label_DOP_RETURN_NIL,
&&label_DOP_ADD_INTEGER,
&&label_DOP_ADD_IMMEDIATE,
&&label_DOP_ADD_REAL,
&&label_DOP_ADD,
&&label_DOP_SUBTRACT_INTEGER,
&&label_DOP_SUBTRACT_REAL,
&&label_DOP_SUBTRACT,
&&label_DOP_MULTIPLY_INTEGER,
&&label_DOP_MULTIPLY_IMMEDIATE,
&&label_DOP_MULTIPLY_REAL,
&&label_DOP_MULTIPLY,
&&label_DOP_DIVIDE_INTEGER,
&&label_DOP_DIVIDE_IMMEDIATE,
&&label_DOP_DIVIDE_REAL,
&&label_DOP_DIVIDE,
&&label_DOP_BAND,
&&label_DOP_BOR,
&&label_DOP_BXOR,
&&label_DOP_BNOT,
&&label_DOP_SHIFT_LEFT,
&&label_DOP_SHIFT_LEFT_IMMEDIATE,
&&label_DOP_SHIFT_RIGHT,
&&label_DOP_SHIFT_RIGHT_IMMEDIATE,
&&label_DOP_SHIFT_RIGHT_UNSIGNED,
&&label_DOP_SHIFT_RIGHT_UNSIGNED_IMMEDIATE,
&&label_DOP_MOVE_FAR,
&&label_DOP_MOVE_NEAR,
&&label_DOP_JUMP,
&&label_DOP_JUMP_IF,
&&label_DOP_JUMP_IF_NOT,
&&label_DOP_GREATER_THAN,
&&label_DOP_LESS_THAN,
&&label_DOP_EQUALS,
&&label_DOP_COMPARE,
&&label_DOP_LOAD_NIL,
&&label_DOP_LOAD_TRUE,
&&label_DOP_LOAD_FALSE,
&&label_DOP_LOAD_INTEGER,
&&label_DOP_LOAD_CONSTANT,
&&label_DOP_LOAD_UPVALUE,
&&label_DOP_LOAD_SELF,
&&label_DOP_SET_UPVALUE,
&&label_DOP_CLOSURE,
&&label_DOP_PUSH,
&&label_DOP_PUSH_2,
&&label_DOP_PUSH_3,
&&label_DOP_PUSH_ARRAY,
&&label_DOP_CALL,
&&label_DOP_TAILCALL,
&&label_DOP_TRANSFER,
&&label_DOP_GET,
&&label_DOP_PUT,
&&label_DOP_GET_INDEX,
&&label_DOP_PUT_INDEX,
&&label_DOP_LENGTH,
&&label_unknown_op
};
#else
#define VM_START() for(;;){switch(*pc & 0xFF){
#define VM_END() }}
#define VM_OP(op) case op :
#define VM_DEFAULT() default:
#define vm_next() continue #define vm_next() continue
#define vm_checkgc_next() dst_maybe_collect(); continue #endif
#define vm_checkgc_next() dst_maybe_collect(); vm_next()
/* Used to extract bits from the opcode that correspond to arguments. /* Used to extract bits from the opcode that correspond to arguments.
* Pulls out unsigned integers */ * Pulls out unsigned integers */
@ -125,79 +201,74 @@ static int dst_continue(Dst *returnreg) {
* to this loop, adding the opcode to opcodes.h, and adding it to the assembler. * 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 * Some opcodes, especially ones that do arithmetic, are almost entirely
* templated by the above macros. */ * templated by the above macros. */
for (;;) { VM_START();
/*dst_puts(dst_formatc("trace: %C\n", dst_asm_decode_instruction(*pc)));*/ VM_DEFAULT();
switch (*pc & 0xFF) {
default:
retreg = dst_wrap_string(dst_formatc("unknown opcode %d", *pc & 0xFF)); retreg = dst_wrap_string(dst_formatc("unknown opcode %d", *pc & 0xFF));
goto vm_error; goto vm_error;
case DOP_NOOP: VM_OP(DOP_NOOP)
pc++; pc++;
vm_next(); vm_next();
case DOP_ERROR: VM_OP(DOP_ERROR)
retreg = stack[oparg(1, 0xFF)]; retreg = stack[oparg(1, 0xFF)];
goto vm_error; goto vm_error;
case DOP_TYPECHECK: VM_OP(DOP_TYPECHECK)
vm_assert((1 << dst_type(stack[oparg(1, 0xFF)])) & oparg(2, 0xFFFF), vm_assert((1 << dst_type(stack[oparg(1, 0xFF)])) & oparg(2, 0xFFFF), "typecheck failed");
"typecheck failed");
pc++; pc++;
vm_next(); vm_next();
case DOP_RETURN: VM_OP(DOP_RETURN)
retreg = stack[oparg(1, 0xFFFFFF)]; retreg = stack[oparg(1, 0xFFFFFF)];
goto vm_return; goto vm_return;
case DOP_RETURN_NIL: VM_OP(DOP_RETURN_NIL)
retreg = dst_wrap_nil(); retreg = dst_wrap_nil();
goto vm_return; goto vm_return;
case DOP_ADD_INTEGER: VM_OP(DOP_ADD_INTEGER)
vm_binop_integer(+); vm_binop_integer(+);
case DOP_ADD_IMMEDIATE: VM_OP(DOP_ADD_IMMEDIATE)
vm_binop_immediate(+); vm_binop_immediate(+);
case DOP_ADD_REAL: VM_OP(DOP_ADD_REAL)
vm_binop_real(+); vm_binop_real(+);
case DOP_ADD: VM_OP(DOP_ADD)
vm_binop(+); vm_binop(+);
case DOP_SUBTRACT_INTEGER: VM_OP(DOP_SUBTRACT_INTEGER)
vm_binop_integer(-); vm_binop_integer(-);
case DOP_SUBTRACT_REAL: VM_OP(DOP_SUBTRACT_REAL)
vm_binop_real(-); vm_binop_real(-);
case DOP_SUBTRACT: VM_OP(DOP_SUBTRACT)
vm_binop(-); vm_binop(-);
case DOP_MULTIPLY_INTEGER: VM_OP(DOP_MULTIPLY_INTEGER)
vm_binop_integer(*); vm_binop_integer(*);
case DOP_MULTIPLY_IMMEDIATE: VM_OP(DOP_MULTIPLY_IMMEDIATE)
vm_binop_immediate(*); vm_binop_immediate(*);
case DOP_MULTIPLY_REAL: VM_OP(DOP_MULTIPLY_REAL)
vm_binop_real(*); vm_binop_real(*);
case DOP_MULTIPLY: VM_OP(DOP_MULTIPLY)
vm_binop(*); vm_binop(*);
case DOP_DIVIDE_INTEGER: VM_OP(DOP_DIVIDE_INTEGER)
vm_assert(dst_unwrap_integer(stack[oparg(3, 0xFF)]) != 0, "integer divide error"); vm_assert(dst_unwrap_integer(stack[oparg(3, 0xFF)]) != 0, "integer divide error");
vm_assert(!(dst_unwrap_integer(stack[oparg(3, 0xFF)]) == -1 && vm_assert(!(dst_unwrap_integer(stack[oparg(3, 0xFF)]) == -1 &&
dst_unwrap_integer(stack[oparg(2, 0xFF)]) == INT32_MIN), dst_unwrap_integer(stack[oparg(2, 0xFF)]) == INT32_MIN),
"integer divide error"); "integer divide error");
vm_binop_integer(/); vm_binop_integer(/);
case DOP_DIVIDE_IMMEDIATE: VM_OP(DOP_DIVIDE_IMMEDIATE)
{ {
int32_t op1 = dst_unwrap_integer(stack[oparg(2, 0xFF)]); int32_t op1 = dst_unwrap_integer(stack[oparg(2, 0xFF)]);
int32_t op2 = *((int32_t *)pc) >> 24; int32_t op2 = *((int32_t *)pc) >> 24;
@ -214,10 +285,10 @@ static int dst_continue(Dst *returnreg) {
vm_next(); vm_next();
} }
case DOP_DIVIDE_REAL: VM_OP(DOP_DIVIDE_REAL)
vm_binop_real(/); vm_binop_real(/);
case DOP_DIVIDE: VM_OP(DOP_DIVIDE)
{ {
Dst op1 = stack[oparg(2, 0xFF)]; Dst op1 = stack[oparg(2, 0xFF)];
Dst op2 = stack[oparg(3, 0xFF)]; Dst op2 = stack[oparg(3, 0xFF)];
@ -239,20 +310,20 @@ static int dst_continue(Dst *returnreg) {
vm_next(); vm_next();
} }
case DOP_BAND: VM_OP(DOP_BAND)
vm_binop_integer(&); vm_binop_integer(&);
case DOP_BOR: VM_OP(DOP_BOR)
vm_binop_integer(|); vm_binop_integer(|);
case DOP_BXOR: VM_OP(DOP_BXOR)
vm_binop_integer(^); vm_binop_integer(^);
case DOP_BNOT: VM_OP(DOP_BNOT)
stack[oparg(1, 0xFF)] = dst_wrap_integer(~dst_unwrap_integer(stack[oparg(2, 0xFFFF)])); stack[oparg(1, 0xFF)] = dst_wrap_integer(~dst_unwrap_integer(stack[oparg(2, 0xFFFF)]));
vm_next(); vm_next();
case DOP_SHIFT_RIGHT_UNSIGNED: VM_OP(DOP_SHIFT_RIGHT_UNSIGNED)
stack[oparg(1, 0xFF)] = dst_wrap_integer( stack[oparg(1, 0xFF)] = dst_wrap_integer(
(int32_t)(((uint32_t)dst_unwrap_integer(stack[oparg(2, 0xFF)])) (int32_t)(((uint32_t)dst_unwrap_integer(stack[oparg(2, 0xFF)]))
>> >>
@ -261,48 +332,48 @@ static int dst_continue(Dst *returnreg) {
pc++; pc++;
vm_next(); vm_next();
case DOP_SHIFT_RIGHT_UNSIGNED_IMMEDIATE: VM_OP(DOP_SHIFT_RIGHT_UNSIGNED_IMMEDIATE)
stack[oparg(1, 0xFF)] = dst_wrap_integer( stack[oparg(1, 0xFF)] = dst_wrap_integer(
(int32_t) (((uint32_t)dst_unwrap_integer(stack[oparg(2, 0xFF)])) >> oparg(3, 0xFF)) (int32_t) (((uint32_t)dst_unwrap_integer(stack[oparg(2, 0xFF)])) >> oparg(3, 0xFF))
); );
pc++; pc++;
vm_next(); vm_next();
case DOP_SHIFT_RIGHT: VM_OP(DOP_SHIFT_RIGHT)
vm_binop_integer(>>); vm_binop_integer(>>);
case DOP_SHIFT_RIGHT_IMMEDIATE: VM_OP(DOP_SHIFT_RIGHT_IMMEDIATE)
stack[oparg(1, 0xFF)] = dst_wrap_integer( stack[oparg(1, 0xFF)] = dst_wrap_integer(
(int32_t)(dst_unwrap_integer(stack[oparg(2, 0xFF)]) >> oparg(3, 0xFF)) (int32_t)(dst_unwrap_integer(stack[oparg(2, 0xFF)]) >> oparg(3, 0xFF))
); );
pc++; pc++;
vm_next(); vm_next();
case DOP_SHIFT_LEFT: VM_OP(DOP_SHIFT_LEFT)
vm_binop_integer(<<); vm_binop_integer(<<);
case DOP_SHIFT_LEFT_IMMEDIATE: VM_OP(DOP_SHIFT_LEFT_IMMEDIATE)
stack[oparg(1, 0xFF)] = dst_wrap_integer( stack[oparg(1, 0xFF)] = dst_wrap_integer(
dst_unwrap_integer(stack[oparg(2, 0xFF)]) << oparg(3, 0xFF) dst_unwrap_integer(stack[oparg(2, 0xFF)]) << oparg(3, 0xFF)
); );
pc++; pc++;
vm_next(); vm_next();
case DOP_MOVE_NEAR: VM_OP(DOP_MOVE_NEAR)
stack[oparg(1, 0xFF)] = stack[oparg(2, 0xFFFF)]; stack[oparg(1, 0xFF)] = stack[oparg(2, 0xFFFF)];
pc++; pc++;
vm_next(); vm_next();
case DOP_MOVE_FAR: VM_OP(DOP_MOVE_FAR)
stack[oparg(2, 0xFFFF)] = stack[oparg(1, 0xFF)]; stack[oparg(2, 0xFFFF)] = stack[oparg(1, 0xFF)];
pc++; pc++;
vm_next(); vm_next();
case DOP_JUMP: VM_OP(DOP_JUMP)
pc += (*(int32_t *)pc) >> 8; pc += (*(int32_t *)pc) >> 8;
vm_next(); vm_next();
case DOP_JUMP_IF: VM_OP(DOP_JUMP_IF)
if (dst_truthy(stack[oparg(1, 0xFF)])) { if (dst_truthy(stack[oparg(1, 0xFF)])) {
pc += (*(int32_t *)pc) >> 16; pc += (*(int32_t *)pc) >> 16;
} else { } else {
@ -310,7 +381,7 @@ static int dst_continue(Dst *returnreg) {
} }
vm_next(); vm_next();
case DOP_JUMP_IF_NOT: VM_OP(DOP_JUMP_IF_NOT)
if (dst_truthy(stack[oparg(1, 0xFF)])) { if (dst_truthy(stack[oparg(1, 0xFF)])) {
pc++; pc++;
} else { } else {
@ -318,7 +389,7 @@ static int dst_continue(Dst *returnreg) {
} }
vm_next(); vm_next();
case DOP_LESS_THAN: VM_OP(DOP_LESS_THAN)
stack[oparg(1, 0xFF)] = dst_wrap_boolean(dst_compare( stack[oparg(1, 0xFF)] = dst_wrap_boolean(dst_compare(
stack[oparg(2, 0xFF)], stack[oparg(2, 0xFF)],
stack[oparg(3, 0xFF)] stack[oparg(3, 0xFF)]
@ -326,7 +397,7 @@ static int dst_continue(Dst *returnreg) {
pc++; pc++;
vm_next(); vm_next();
case DOP_GREATER_THAN: VM_OP(DOP_GREATER_THAN)
stack[oparg(1, 0xFF)] = dst_wrap_boolean(dst_compare( stack[oparg(1, 0xFF)] = dst_wrap_boolean(dst_compare(
stack[oparg(2, 0xFF)], stack[oparg(2, 0xFF)],
stack[oparg(3, 0xFF)] stack[oparg(3, 0xFF)]
@ -334,7 +405,7 @@ static int dst_continue(Dst *returnreg) {
pc++; pc++;
vm_next(); vm_next();
case DOP_EQUALS: VM_OP(DOP_EQUALS)
stack[oparg(1, 0xFF)] = dst_wrap_boolean(dst_equals( stack[oparg(1, 0xFF)] = dst_wrap_boolean(dst_equals(
stack[oparg(2, 0xFF)], stack[oparg(2, 0xFF)],
stack[oparg(3, 0xFF)] stack[oparg(3, 0xFF)]
@ -342,7 +413,7 @@ static int dst_continue(Dst *returnreg) {
pc++; pc++;
vm_next(); vm_next();
case DOP_COMPARE: VM_OP(DOP_COMPARE)
stack[oparg(1, 0xFF)] = dst_wrap_integer(dst_compare( stack[oparg(1, 0xFF)] = dst_wrap_integer(dst_compare(
stack[oparg(2, 0xFF)], stack[oparg(2, 0xFF)],
stack[oparg(3, 0xFF)] stack[oparg(3, 0xFF)]
@ -350,27 +421,27 @@ static int dst_continue(Dst *returnreg) {
pc++; pc++;
vm_next(); vm_next();
case DOP_LOAD_NIL: VM_OP(DOP_LOAD_NIL)
stack[oparg(1, 0xFFFFFF)] = dst_wrap_nil(); stack[oparg(1, 0xFFFFFF)] = dst_wrap_nil();
pc++; pc++;
vm_next(); vm_next();
case DOP_LOAD_TRUE: VM_OP(DOP_LOAD_TRUE)
stack[oparg(1, 0xFFFFFF)] = dst_wrap_boolean(1); stack[oparg(1, 0xFFFFFF)] = dst_wrap_boolean(1);
pc++; pc++;
vm_next(); vm_next();
case DOP_LOAD_FALSE: VM_OP(DOP_LOAD_FALSE)
stack[oparg(1, 0xFFFFFF)] = dst_wrap_boolean(0); stack[oparg(1, 0xFFFFFF)] = dst_wrap_boolean(0);
pc++; pc++;
vm_next(); vm_next();
case DOP_LOAD_INTEGER: VM_OP(DOP_LOAD_INTEGER)
stack[oparg(1, 0xFF)] = dst_wrap_integer(*((int32_t *)pc) >> 16); stack[oparg(1, 0xFF)] = dst_wrap_integer(*((int32_t *)pc) >> 16);
pc++; pc++;
vm_next(); vm_next();
case DOP_LOAD_CONSTANT: VM_OP(DOP_LOAD_CONSTANT)
{ {
int32_t index = oparg(2, 0xFFFF); int32_t index = oparg(2, 0xFFFF);
vm_assert(index < func->def->constants_length, "invalid constant"); vm_assert(index < func->def->constants_length, "invalid constant");
@ -379,12 +450,12 @@ static int dst_continue(Dst *returnreg) {
vm_next(); vm_next();
} }
case DOP_LOAD_SELF: VM_OP(DOP_LOAD_SELF)
stack[oparg(1, 0xFFFFFF)] = dst_wrap_function(func); stack[oparg(1, 0xFFFFFF)] = dst_wrap_function(func);
pc++; pc++;
vm_next(); vm_next();
case DOP_LOAD_UPVALUE: VM_OP(DOP_LOAD_UPVALUE)
{ {
int32_t eindex = oparg(2, 0xFF); int32_t eindex = oparg(2, 0xFF);
int32_t vindex = oparg(3, 0xFF); int32_t vindex = oparg(3, 0xFF);
@ -403,7 +474,7 @@ static int dst_continue(Dst *returnreg) {
vm_next(); vm_next();
} }
case DOP_SET_UPVALUE: VM_OP(DOP_SET_UPVALUE)
{ {
int32_t eindex = oparg(2, 0xFF); int32_t eindex = oparg(2, 0xFF);
int32_t vindex = oparg(3, 0xFF); int32_t vindex = oparg(3, 0xFF);
@ -420,7 +491,7 @@ static int dst_continue(Dst *returnreg) {
vm_next(); vm_next();
} }
case DOP_CLOSURE: VM_OP(DOP_CLOSURE)
{ {
DstFuncDef *fd; DstFuncDef *fd;
vm_assert((int32_t)oparg(2, 0xFFFF) < func->def->defs_length, "invalid funcdef"); vm_assert((int32_t)oparg(2, 0xFFFF) < func->def->defs_length, "invalid funcdef");
@ -430,13 +501,13 @@ static int dst_continue(Dst *returnreg) {
vm_checkgc_next(); vm_checkgc_next();
} }
case DOP_PUSH: VM_OP(DOP_PUSH)
dst_fiber_push(dst_vm_fiber, stack[oparg(1, 0xFFFFFF)]); dst_fiber_push(dst_vm_fiber, stack[oparg(1, 0xFFFFFF)]);
pc++; pc++;
stack = dst_vm_fiber->data + dst_vm_fiber->frame; stack = dst_vm_fiber->data + dst_vm_fiber->frame;
vm_checkgc_next(); vm_checkgc_next();
case DOP_PUSH_2: VM_OP(DOP_PUSH_2)
dst_fiber_push2(dst_vm_fiber, dst_fiber_push2(dst_vm_fiber,
stack[oparg(1, 0xFF)], stack[oparg(1, 0xFF)],
stack[oparg(2, 0xFFFF)]); stack[oparg(2, 0xFFFF)]);
@ -444,7 +515,7 @@ static int dst_continue(Dst *returnreg) {
stack = dst_vm_fiber->data + dst_vm_fiber->frame; stack = dst_vm_fiber->data + dst_vm_fiber->frame;
vm_checkgc_next(); vm_checkgc_next();
case DOP_PUSH_3: VM_OP(DOP_PUSH_3)
dst_fiber_push3(dst_vm_fiber, dst_fiber_push3(dst_vm_fiber,
stack[oparg(1, 0xFF)], stack[oparg(1, 0xFF)],
stack[oparg(2, 0xFF)], stack[oparg(2, 0xFF)],
@ -453,7 +524,7 @@ static int dst_continue(Dst *returnreg) {
stack = dst_vm_fiber->data + dst_vm_fiber->frame; stack = dst_vm_fiber->data + dst_vm_fiber->frame;
vm_checkgc_next(); vm_checkgc_next();
case DOP_PUSH_ARRAY: VM_OP(DOP_PUSH_ARRAY)
{ {
const Dst *vals; const Dst *vals;
int32_t len; int32_t len;
@ -467,7 +538,7 @@ static int dst_continue(Dst *returnreg) {
stack = dst_vm_fiber->data + dst_vm_fiber->frame; stack = dst_vm_fiber->data + dst_vm_fiber->frame;
vm_checkgc_next(); vm_checkgc_next();
case DOP_CALL: VM_OP(DOP_CALL)
{ {
Dst callee = stack[oparg(2, 0xFFFF)]; Dst callee = stack[oparg(2, 0xFFFF)];
if (dst_checktype(callee, DST_FUNCTION)) { if (dst_checktype(callee, DST_FUNCTION)) {
@ -492,7 +563,7 @@ static int dst_continue(Dst *returnreg) {
vm_throw("expected function"); vm_throw("expected function");
} }
case DOP_TAILCALL: VM_OP(DOP_TAILCALL)
{ {
Dst callee = stack[oparg(1, 0xFFFFFF)]; Dst callee = stack[oparg(1, 0xFFFFFF)];
if (dst_checktype(callee, DST_FUNCTION)) { if (dst_checktype(callee, DST_FUNCTION)) {
@ -516,7 +587,7 @@ static int dst_continue(Dst *returnreg) {
vm_throw("expected function"); vm_throw("expected function");
} }
case DOP_TRANSFER: VM_OP(DOP_TRANSFER)
{ {
int status; int status;
DstFiber *nextfiber; DstFiber *nextfiber;
@ -561,34 +632,39 @@ static int dst_continue(Dst *returnreg) {
vm_checkgc_next(); vm_checkgc_next();
} }
case DOP_PUT: VM_OP(DOP_PUT)
dst_put(stack[oparg(1, 0xFF)], dst_put(stack[oparg(1, 0xFF)],
stack[oparg(2, 0xFF)], stack[oparg(2, 0xFF)],
stack[oparg(3, 0xFF)]); stack[oparg(3, 0xFF)]);
++pc; ++pc;
vm_checkgc_next(); vm_checkgc_next();
case DOP_PUT_INDEX: VM_OP(DOP_PUT_INDEX)
dst_setindex(stack[oparg(1, 0xFF)], dst_setindex(stack[oparg(1, 0xFF)],
stack[oparg(2, 0xFF)], stack[oparg(2, 0xFF)],
oparg(3, 0xFF)); oparg(3, 0xFF));
++pc; ++pc;
vm_checkgc_next(); vm_checkgc_next();
case DOP_GET: VM_OP(DOP_GET)
stack[oparg(1, 0xFF)] = dst_get( stack[oparg(1, 0xFF)] = dst_get(
stack[oparg(2, 0xFF)], stack[oparg(2, 0xFF)],
stack[oparg(3, 0xFF)]); stack[oparg(3, 0xFF)]);
++pc; ++pc;
vm_next(); vm_next();
case DOP_GET_INDEX: VM_OP(DOP_GET_INDEX)
stack[oparg(1, 0xFF)] = dst_getindex( stack[oparg(1, 0xFF)] = dst_getindex(
stack[oparg(2, 0xFF)], stack[oparg(2, 0xFF)],
oparg(3, 0xFF)); oparg(3, 0xFF));
++pc; ++pc;
vm_next(); vm_next();
VM_OP(DOP_LENGTH)
stack[oparg(1, 0xFF)] = dst_wrap_integer(dst_length(stack[oparg(2, 0xFFFF)]));
++pc;
vm_next();
/* Return from c function. Simpler than retuning from dst function */ /* Return from c function. Simpler than retuning from dst function */
vm_return_cfunc: vm_return_cfunc:
{ {
@ -645,9 +721,7 @@ static int dst_continue(Dst *returnreg) {
vm_checkgc_next(); vm_checkgc_next();
} }
} /* end switch */ VM_END()
} /* end for */
#undef oparg #undef oparg