Exemplo n.º 1
0
PUBLIC void vm_raise(VMSTATE vms, OBJ exception, OBJ arg) {
  if (vms->r->vm_trap_closure != NULL) {
    VECTOR argvec = newvector_noinit(5);

    push_frame(vms);

#ifdef DEBUG
    printf("%p raising %s\n", current_thread, ((BVECTOR) AT((OVECTOR) exception, SY_NAME))->vec);
#endif

    ATPUT(argvec, 0, NULL);
    ATPUT(argvec, 1, exception);
    ATPUT(argvec, 2, arg);
    ATPUT(argvec, 3, (OBJ) getcont_from(vms));
    ATPUT(argvec, 4, vms->r->vm_acc);

    vms->c.vm_top = 0;
    apply_closure(vms, vms->r->vm_trap_closure, argvec);
    vms->r->vm_frame = NULL;	/* If it ever returns, the thread dies. */
  } else {
    if (OVECTORP(exception) && ((OVECTOR) exception)->type == T_SYMBOL)
      fprintf(stderr, "excp sym = '%s\n", ((BVECTOR) AT((OVECTOR) exception, SY_NAME))->vec);
    if (OVECTORP(arg) && ((OVECTOR) arg)->type == T_SYMBOL)
      fprintf(stderr, "arg sym = '%s\n", ((BVECTOR) AT((OVECTOR) arg, SY_NAME))->vec);
    if (BVECTORP(arg))
      fprintf(stderr, "arg str = %s\n", ((BVECTOR) arg)->vec);
    fprintf(stderr,
	    "Exception raised, no handler installed -> vm death.\n");
    vms->c.vm_state = VM_STATE_DYING;
  }
}
Exemplo n.º 2
0
// socket-send
scm_obj_t
subr_socket_send(VM* vm, int argc, scm_obj_t argv[])
{
    if (argc == 3) {
        if (SOCKETP(argv[0])) {
            if (BVECTORP(argv[1])) {
                int m_flags;
                CONVERT_TO_MACHINE_INT(2, "socket-send", &m_flags);
                scm_socket_t socket = (scm_socket_t)argv[0];
                if (socket->fd != INVALID_SOCKET) {
                    try {
                        scm_bvector_t bv = (scm_bvector_t)argv[1];
                        return MAKEFIXNUM(socket_send(socket, bv->elts, bv->count, m_flags));
                    } catch (io_exception_t& e) {
                        raise_io_error(vm, "socket-send", e.m_operation, e.m_message, e.m_err, socket, scm_false);
                        return scm_undef;
                    }
                }
                wrong_type_argument_violation(vm, "socket-send", 0, "connected socket", argv[0], argc, argv);
                return scm_undef;
            }
            wrong_type_argument_violation(vm, "socket-send", 1, "bytevector", argv[1], argc, argv);
            return scm_undef;
        }
        wrong_type_argument_violation(vm, "socket-send", 0, "socket", argv[0], argc, argv);
        return scm_undef;
    }
    wrong_number_of_arguments_violation(vm, "socket-send", 3, 3, argc, argv);
    return scm_undef;
}
Exemplo n.º 3
0
// shared-bag-put!
scm_obj_t
subr_shared_bag_put(VM* vm, int argc, scm_obj_t argv[])
{
#if USE_PARALLEL_VM
    if (argc == 3 || argc == 4) {
        if (SHAREDBAGP(argv[0])) {
            if (STRINGP(argv[1])) {
                int timeout = 0;
                if (argc == 4) {
                    if (FIXNUMP(argv[3]) && FIXNUM(argv[3]) >= 0) {
                        timeout = FIXNUM(argv[3]);
                    } else {
                        wrong_type_argument_violation(vm, "shared-bag-put!", 3, "non-negative fixnum", argv[3], argc, argv);
                        return scm_undef;
                    }
                }
                scm_string_t string = (scm_string_t)argv[1];
                sharedbag_slot_t* slot = lookup_sharedbag((scm_sharedbag_t)argv[0], string->name, string->size);
                assert(slot);
#if CYCLIC_CHECK_BEFORE_SERIALIZE
                if (cyclic_objectp(vm->m_heap, argv[2])) {
                    serialize_cyclic_object_violation(vm, "shared-bag-put!", argv[2], argc, argv);
                    return scm_undef;
                }
#endif
                scm_obj_t obj = serializer_t(vm->m_heap).translate(argv[2]);
                if (BVECTORP(obj)) {
                    scm_bvector_t bvector = (scm_bvector_t)obj;
                    int id = slot->buf.put(bvector->elts, bvector->count);
                    if (slot->queue.wait_lock_try_put(id)) return scm_true;
                    if (argc == 4) {
                        vm->m_interp->update(vm, VM_STATE_BLOCK);
                        bool succ = slot->queue.put(id, timeout);
                        vm->m_interp->update(vm, VM_STATE_ACTIVE);
                        if (succ) return scm_true;
                        if (slot->queue.no_more_put()) return scm_shutdown;
                        return scm_timeout;
                    } else {
                        vm->m_interp->update(vm, VM_STATE_BLOCK);
                        bool succ = slot->queue.put(id);
                        vm->m_interp->update(vm, VM_STATE_ACTIVE);
                        return succ ? scm_true : scm_shutdown;
                    }
                }
                non_serializable_object_violation(vm, "shared-bag-put!", obj, argc, argv);
                return scm_undef;
            }
            wrong_type_argument_violation(vm, "shared-bag-put!", 1, "string", argv[1], argc, argv);
            return scm_undef;
        }
        wrong_type_argument_violation(vm, "shared-bag-put!", 0, "shared bag", argv[0], argc, argv);
        return scm_undef;
    }
    wrong_number_of_arguments_violation(vm, "shared-bag-put!", 3, 4, argc, argv);
    return scm_undef;
#else
    fatal("%s:%u shared-bag-put! not supported on this build", __FILE__, __LINE__);
#endif
}
Exemplo n.º 4
0
PRIVATE OBJ strSearchBody(VMSTATE vms, VECTOR argvec, int case_matters) {
  OBJ str = ARG(0);
  OBJ pat = ARG(1);
  uint8_t const *pos;

  TYPEERRIF(!BVECTORP(str) || !BVECTORP(pat));

  if (case_matters)
    pos = strSearchAux(((BVECTOR) str)->vec, str->length,
		       ((BVECTOR) pat)->vec, pat->length);
  else
    pos = strSearchAuxCI(((BVECTOR) str)->vec, str->length,
			 ((BVECTOR) pat)->vec, pat->length);

  if (pos == NULL)
    return false;
  else
    return MKNUM(pos - ((BVECTOR) str)->vec);
}
Exemplo n.º 5
0
PRIVATE BVECTOR getPrintString_body(VMSTATE vms, OBJ x, int depth) {
  char buf[80];

  if (x == NULL)
    return newstring("null");

  if (NUMP(x)) {
    sprintf(buf, "%ld", (long) NUM(x));
    return newstring(buf);
  }

  if (SINGLETONP(x)) {
    if (x == true) return newstring("true");
    if (x == false) return newstring("false");
    if (x == undefined) return newstring("undefined");
    return newstring("#<unknown-singleton>");
  }

  if (OBJECTP(x))
    return newstring("#<object>");

  if (BVECTORP(x))
    return (BVECTOR) x;

  if (OVECTORP(x)) {
    OVECTOR ov = (OVECTOR) x;

    switch (ov->type) {
      case T_HASHTABLE: return newstring("#<hashtable>");
      case T_SLOT: return newstring("#<slot>");
      case T_METHOD: return newstring("#<method>");
      case T_CLOSURE: return newstring("#<closure>");
      case T_SYMBOL: return (BVECTOR) AT(ov, SY_NAME);
      case T_PRIM: return bvector_concat(newstring("#<prim "),
					 bvector_concat((BVECTOR) AT((OVECTOR) AT(ov, PR_NAME),
								     SY_NAME),
							newstring(">")));
      case T_FRAME: return newstring("#<frame>");
      case T_VMREGS: return newstring("#<vmregs>");
      case T_CONNECTION: return newstring("#<connection>");
      case T_CONTINUATION: return newstring("#<continuation>");
      case T_USERHASHLINK: return newstring("#<hashlink>");
      default: return newstring("#<unknown-ovector-type>");
    }
  }

  if (VECTORP(x)) {
    if (depth < 5) {
      VECTOR v = (VECTOR) x;
      BVECTOR result = newstring("[");
      int i;

      for (i = 0; i < (int) x->length - 1; i++) {
	result = bvector_concat(result, getPrintString_body(vms, AT(v, i), depth + 1));
	result = bvector_concat(result, newstring(", "));
      }

      if (x->length > 0)
	result = bvector_concat(result, getPrintString_body(vms, AT(v, x->length - 1), depth + 1));

      return bvector_concat(result, newstring("]"));
    } else
      return newstring("[...]");
  }

  return newstring("unhandled-type-getPrintString");
}
Exemplo n.º 6
0
// shared-queue-push!
scm_obj_t
subr_shared_queue_push(VM* vm, int argc, scm_obj_t argv[])
{
#if USE_PARALLEL_VM
    if (argc == 2 || argc == 3) {
        if (SHAREDQUEUEP(argv[0])) {
            int timeout = 0;
            if (argc == 3) {
                if (FIXNUMP(argv[2]) && FIXNUM(argv[2]) >= 0) {
                    timeout = FIXNUM(argv[2]);
                } else {
                    wrong_type_argument_violation(vm, "shared-queue-push!", 2, "non-negative fixnum", argv[2], argc, argv);
                    return scm_undef;
                }
            }
            scm_sharedqueue_t queue = (scm_sharedqueue_t)argv[0];
            intptr_t id;
#if USE_SHARED_QUEUE_QUICK_ENCODE
            if (FIXNUMP(argv[1])) {
                id = FIXNUM(argv[1]) | INTPTR_MIN;
            }
            else if (argv[1] == scm_true) {
                id = INTPTR_MAX;
            }
            else if (argv[1] == scm_false) {
                id = INTPTR_MAX - 1;
            }
            else
#endif
            {
#if CYCLIC_CHECK_BEFORE_SERIALIZE
                if (cyclic_objectp(vm->m_heap, argv[1])) {
                    serialize_cyclic_object_violation(vm, "shared-queue-push!", argv[1], argc, argv);
                    return scm_undef;
                }
#endif
                scm_obj_t obj = serializer_t(vm->m_heap).translate(argv[1]);
                if (BVECTORP(obj)) {
                    scm_bvector_t bvector = (scm_bvector_t)obj;
                    id = queue->buf.put(bvector->elts, bvector->count);
                } else {
                    non_serializable_object_violation(vm, "shared-queue-push!", obj, argc, argv);
                    return scm_undef;
                }
            }
            if (queue->queue.wait_lock_try_put(id)) return scm_true;
            if (argc == 3) {
                vm->m_interp->update(vm, VM_STATE_BLOCK);
                bool succ = queue->queue.put(id, timeout);
                vm->m_interp->update(vm, VM_STATE_ACTIVE);
                if (succ) return scm_true;
                if (queue->queue.no_more_put()) return scm_shutdown;
                return scm_timeout;
            } else {
                vm->m_interp->update(vm, VM_STATE_BLOCK);
                bool succ = queue->queue.put(id);
                vm->m_interp->update(vm, VM_STATE_ACTIVE);
                return succ ? scm_true : scm_shutdown;
            }
        }
        wrong_type_argument_violation(vm, "shared-queue-push!", 0, "shared queue", argv[0], argc, argv);
        return scm_undef;
    }
    wrong_number_of_arguments_violation(vm, "shared-queue-push!", 2, 3, argc, argv);
    return scm_undef;
#else
    fatal("%s:%u shared-queue-push! not supported on this build", __FILE__, __LINE__);
#endif
}
Exemplo n.º 7
0
PUBLIC int run_vm(VMSTATE vms) {
  OBJ vm_hold;	/* Holding register. NOT SEEN BY GC */
  int ticks_left = VM_TIMESLICE_TICKS;

  while (vms->c.vm_state != VM_STATE_DYING && ticks_left-- && vms->r->vm_acc != yield_thread) {
    if (vms->c.vm_state > 0) {
      vms->c.vm_state--;
      if (vms->c.vm_state == 0) {
	/* Quota expired. Warn. */
	vms->c.vm_state = VM_DEFAULT_CPU_QUOTA;
	vm_raise(vms, (OBJ) newsym("quota-expired"), NULL);
	/* Make sure we don't recurse :-) */
	vms->r->vm_trap_closure = NULL;
      }
    }

    gc_reach_safepoint();

#ifdef DEBUG
    debug_dump_instr( vms->r->vm_code->vec , vms->c.vm_ip );
#endif

    switch (CODEAT(vms->c.vm_ip)) {
      case OP_AT: {
	int index = CODEAT(vms->c.vm_ip + 1);

	if (index < 0 || index >= vms->r->vm_acc->length) {
	  vm_raise(vms, (OBJ) newsym("range-check-error"), vms->r->vm_acc);
	  break;
	}

	if (!VECTORP(vms->r->vm_acc)) {
	  vm_raise(vms, (OBJ) newsym("vm-runtime-type-error"), vms->r->vm_acc);
	  break;
	}

	vms->r->vm_acc = AT((VECTOR) vms->r->vm_acc, index);
	vms->c.vm_ip += 2;
	break;
      }

      case OP_ATPUT: {
	int index = CODEAT(vms->c.vm_ip + 1);

	vm_hold = PEEK();

	if (index < 0 || index >= vm_hold->length) {
	  vm_raise(vms, (OBJ) newsym("range-check-error"), vm_hold);
	  break;
	}

	if (!VECTORP(vm_hold)) {
	  vm_raise(vms, (OBJ) newsym("vm-runtime-type-error"), vm_hold);
	  break;
	}

	ATPUT((VECTOR) vm_hold, index, vms->r->vm_acc);
	vms->c.vm_ip += 2;
	break;
      }

      case OP_MOV_A_LOCL: {
	int i = CODEAT(vms->c.vm_ip + 1);
	vm_hold = (OBJ) vms->r->vm_env;
	while (i-- > 0) vm_hold = AT((VECTOR) vm_hold, 0);
	vms->r->vm_acc = AT((VECTOR) vm_hold, CODEAT(vms->c.vm_ip + 2) + 1);
	vms->c.vm_ip += 3;
	break;
      }

      case OP_MOV_A_GLOB:
	vm_hold = AT(vms->r->vm_lits, CODEAT(vms->c.vm_ip + 1));
	vms->r->vm_acc = AT((OVECTOR) vm_hold, SY_VALUE);
	vms->c.vm_ip += 2;
	break;

      case OP_MOV_A_SLOT: {
	OVECTOR slot, slotname;

	if (!OBJECTP(vms->r->vm_acc)) {
	  vm_raise(vms, (OBJ) newsym("vm-runtime-type-error"), vms->r->vm_acc);
	  break;
	}

	slotname = (OVECTOR) AT(vms->r->vm_lits, CODEAT(vms->c.vm_ip + 1));

	if (!O_CAN_X((OBJECT) vms->r->vm_acc, vms->r->vm_effuid)) {
	  NOPERMISSION((OBJ) slotname);
	}

	slot = findslot((OBJECT) vms->r->vm_acc, slotname, NULL);

	if (slot == NULL) {
	  vm_raise(vms, (OBJ) newsym("slot-not-found"), (OBJ) slotname);
	  break;
	}

	if (!MS_CAN_R(slot, vms->r->vm_effuid)) {
	  NOPERMISSION((OBJ) slotname);
	}

	vms->r->vm_acc = AT(slot, SL_VALUE);
	vms->c.vm_ip += 2;
	break;
      }

      case OP_MOV_A_LITL:
	vms->r->vm_acc = AT(vms->r->vm_lits, CODEAT(vms->c.vm_ip + 1));
	vms->c.vm_ip += 2;
	break;

      case OP_MOV_A_SELF: vms->r->vm_acc = (OBJ) vms->r->vm_self; vms->c.vm_ip++; break;
      case OP_MOV_A_FRAM: vms->r->vm_acc = (OBJ) vms->r->vm_frame; vms->c.vm_ip++; break;

      case OP_MOV_LOCL_A: {
	int i = CODEAT(vms->c.vm_ip + 1);
	vm_hold = (OBJ) vms->r->vm_env;
	while (i-- > 0) vm_hold = AT((VECTOR) vm_hold, 0);
	ATPUT((VECTOR) vm_hold, CODEAT(vms->c.vm_ip + 2) + 1, vms->r->vm_acc);
	vms->c.vm_ip += 3;
	break;
      }

      case OP_MOV_GLOB_A:
	if (!PRIVILEGEDP(vms->r->vm_effuid)) {
	  NOPERMISSION((OBJ) newsym("setting-global-value"));
	}
	vm_hold = AT(vms->r->vm_lits, CODEAT(vms->c.vm_ip + 1));
	ATPUT((OVECTOR) vm_hold, SY_VALUE, vms->r->vm_acc);
	vms->c.vm_ip += 2;
	break;

      case OP_MOV_SLOT_A: {
	OVECTOR slot, slotname;
	OBJECT target = (OBJECT) POP();
	OBJECT foundin;

	if (!OBJECTP(target)) {
	  vm_raise(vms, (OBJ) newsym("vm-runtime-type-error"), (OBJ) target);
	  break;
	}

	slotname = (OVECTOR) AT(vms->r->vm_lits, CODEAT(vms->c.vm_ip + 1));

	if (!O_CAN_X(target, vms->r->vm_effuid)) {
	  NOPERMISSION((OBJ) slotname);
	}

	slot = findslot(target, slotname, &foundin);

	if (slot == NULL) {
	  vm_raise(vms, (OBJ) newsym("slot-not-found"), (OBJ) slotname);
	  break;
	}

	if (!MS_CAN_W(slot, vms->r->vm_effuid)) {
	  NOPERMISSION((OBJ) slotname);
	}

	if (foundin == target) {
	  ATPUT(slot, SL_VALUE, vms->r->vm_acc);
	} else {
	  OVECTOR newslot = addslot(target, slotname, (OBJECT) AT(slot, SL_OWNER));
	  ATPUT(newslot, SL_FLAGS, AT(slot, SL_FLAGS));
	  ATPUT(newslot, SL_VALUE, vms->r->vm_acc);
	}

	vms->c.vm_ip += 2;
	break;
      }

      case OP_MOV_FRAM_A:
	if (!PRIVILEGEDP(vms->r->vm_effuid)) {
	  NOPERMISSION((OBJ) newsym("restoring-vm-frame-pointer"));
	}

	if (!OVECTORP(vms->r->vm_acc) || ((OVECTOR) vms->r->vm_acc)->type != T_FRAME) {
	  vm_raise(vms, (OBJ) newsym("vm-runtime-type-error"), vms->r->vm_acc);
	  break;
	}

	vms->r->vm_frame = (OVECTOR) vms->r->vm_acc;
	vms->c.vm_ip++;
	break;

      case OP_PUSH: PUSH(vms->r->vm_acc); vms->c.vm_ip++; break;
      case OP_POP: vms->r->vm_acc = POP(); vms->c.vm_ip++; break;
      case OP_SWAP:
	vm_hold = POP();
	PUSH(vms->r->vm_acc);
	vms->r->vm_acc = vm_hold;
	vms->c.vm_ip++;
	break;

      case OP_VECTOR:
	vms->r->vm_acc = (OBJ) newvector(CODEAT(vms->c.vm_ip+1));
	vms->c.vm_ip += 2;
	break;
	
      case OP_ENTER_SCOPE:
	vm_hold = (OBJ) newvector(CODEAT(vms->c.vm_ip+1) + 1);
	ATPUT((VECTOR) vm_hold, 0, (OBJ) vms->r->vm_env);
	vms->r->vm_env = (VECTOR) vm_hold;
	vms->c.vm_ip += 2;
	break;

      case OP_LEAVE_SCOPE:
	vms->r->vm_env = (VECTOR) AT(vms->r->vm_env, 0);
	vms->c.vm_ip++;
	break;

      case OP_MAKE_VECTOR: {
	int i = 0;
	int len = CODEAT(vms->c.vm_ip+1);
	VECTOR vec = newvector_noinit(len);

	for (i = len - 1; i >= 0; i--)
	  ATPUT(vec, i, POP());

	vms->r->vm_acc = (OBJ) vec;
	vms->c.vm_ip += 2;
	break;
      }

      case OP_CLOSURE:
	vms->r->vm_acc = make_closure_from((OVECTOR) vms->r->vm_acc,
					   vms->r->vm_self,
					   vms->r->vm_env,
					   vms->r->vm_effuid);
	vms->c.vm_ip++;
	break;

      case OP_METHOD_CLOSURE: {
	OVECTOR methname = (OVECTOR) AT(vms->r->vm_lits, CODEAT(vms->c.vm_ip + 1));
	OVECTOR method;

	if (!OBJECTP(vms->r->vm_acc)) {
	  vm_raise(vms, (OBJ) newsym("vm-runtime-type-error"), vms->r->vm_acc);
	  break;
	}

	method = findmethod((OBJECT) vms->r->vm_acc, methname);

	if (method == NULL) {
	  vm_raise(vms, (OBJ) newsym("method-not-found"), (OBJ) methname);
	  break;
	}

	if (!MS_CAN_R(method, vms->r->vm_effuid)) {
	  NOPERMISSION((OBJ) methname);
	}

	vm_hold = (OBJ) newovector(CL_MAXSLOTINDEX, T_CLOSURE);
	ATPUT((OVECTOR) vm_hold, CL_METHOD, (OBJ) method);
	ATPUT((OVECTOR) vm_hold, CL_SELF, vms->r->vm_acc);
	vms->r->vm_acc = vm_hold;

	vms->c.vm_ip += 2;
	break;
      }

      case OP_RET:
	if (vms->r->vm_frame != NULL) {
	  restoreframe(vms, vms->r->vm_frame);
	  if (vms->r->vm_code != NULL)
	    break;
	}

	vms->c.vm_state = VM_STATE_DYING;
	return 1;	/* finished, nothing more to run! */
	
      case OP_CALL: {
	OVECTOR methname = (OVECTOR) AT(vms->r->vm_lits, CODEAT(vms->c.vm_ip + 1));
	OVECTOR method;

	if (vms->r->vm_acc == NULL || TAGGEDP(vms->r->vm_acc)) {
	  vm_raise(vms,
		   (OBJ) newsym("null-call-error"),
		   AT(vms->r->vm_lits, CODEAT(vms->c.vm_ip+1)));
	  break;
	}

	if (!OBJECTP(vms->r->vm_acc)) {
	  vm_raise(vms, (OBJ) newsym("vm-runtime-type-error"), vms->r->vm_acc);
	  break;
	}

	method = findmethod((OBJECT) vms->r->vm_acc, methname);

	if (method == NULL) {
	  vm_raise(vms, (OBJ) newsym("method-not-found"), (OBJ) methname);
	  break;
	}

	if (!MS_CAN_X(method, vms->r->vm_effuid)) {
	  NOPERMISSION((OBJ) methname);
	}

	vm_hold = POP();
	if (vm_hold->length-1 != NUM(AT(method, ME_ARGC))) {
	  vm_raise(vms, (OBJ) newsym("wrong-argc"), (OBJ) methname);
	  break;
	}

	vms->c.vm_ip += 2;
	push_frame(vms);

	vms->r->vm_env = (VECTOR) vm_hold;
	ATPUT(vms->r->vm_env, 0, AT(method, ME_ENV));
	vms->r->vm_code = (BVECTOR) AT(method, ME_CODE);
	vms->r->vm_lits = (VECTOR) AT(method, ME_LITS);
	vms->r->vm_self = (OBJECT) vms->r->vm_acc;
	if (NUM(AT(method, ME_FLAGS)) & O_SETUID)
	  vms->r->vm_effuid = (OBJECT) AT(method, ME_OWNER);
	vms->r->vm_method = method;
	vms->c.vm_ip = 0;
	break;
      }

      case OP_CALL_AS: {
	OVECTOR methname = (OVECTOR) AT(vms->r->vm_lits, CODEAT(vms->c.vm_ip + 1));
	OVECTOR method;

	if (vms->r->vm_self == NULL ||
	    vms->r->vm_acc == NULL || TAGGEDP(vms->r->vm_acc)) {
	  vm_raise(vms,
		   (OBJ) newsym("null-call-error"),
		   AT(vms->r->vm_lits, CODEAT(vms->c.vm_ip+1)));
	  break;
	}

	if (!OBJECTP(vms->r->vm_acc)) {
	  vm_raise(vms, (OBJ) newsym("vm-runtime-type-error"), vms->r->vm_acc);
	  break;
	}

	method = findmethod((OBJECT) vms->r->vm_acc, methname);

	if (method == NULL) {
	  vm_raise(vms, (OBJ) newsym("method-not-found"), (OBJ) methname);
	  break;
	}

	if (!MS_CAN_X(method, vms->r->vm_effuid)) {
	  NOPERMISSION((OBJ) methname);
	}

	vm_hold = POP();
	if (vm_hold->length-1 != NUM(AT(method, ME_ARGC))) {
	  vm_raise(vms, (OBJ) newsym("wrong-argc"), (OBJ) methname);
	  break;
	}

	vms->c.vm_ip += 2;
	push_frame(vms);

	vms->r->vm_env = (VECTOR) vm_hold;
	ATPUT(vms->r->vm_env, 0, AT(method, ME_ENV));
	vms->r->vm_code = (BVECTOR) AT(method, ME_CODE);
	vms->r->vm_lits = (VECTOR) AT(method, ME_LITS);

	/* don't set vm_self, this is OP_CALL_AS. */
	/* vms->r->vm_self = vms->r->vm_acc; */

	if (NUM(AT(method, ME_FLAGS)) & O_SETUID)
	  vms->r->vm_effuid = (OBJECT) AT(method, ME_OWNER);
	vms->r->vm_method = method;
	vms->c.vm_ip = 0;
	break;
      }

      case OP_APPLY:
	vms->c.vm_ip++;
	apply_closure(vms, (OVECTOR) vms->r->vm_acc, (VECTOR) POP());
	break;

      case OP_JUMP: vms->c.vm_ip += 3 + ((int16_t) CODE16AT(vms->c.vm_ip+1)); break;

      case OP_JUMP_TRUE:
	vms->c.vm_ip += (vms->r->vm_acc == false) ? 3 :
						    3 + ((int16_t) CODE16AT(vms->c.vm_ip+1));
	break;

      case OP_JUMP_FALSE:
	vms->c.vm_ip += (vms->r->vm_acc != false) ? 3 :
						    3 + ((int16_t) CODE16AT(vms->c.vm_ip+1));
	break;

      case OP_NOT:
	vms->r->vm_acc = (vms->r->vm_acc == false) ? true : false;
	vms->c.vm_ip++;
	break;

      case OP_EQ:
	vms->r->vm_acc = (vms->r->vm_acc == POP()) ? true : false;
	vms->c.vm_ip++;
	break;

      case OP_NE:
	vms->r->vm_acc = (vms->r->vm_acc != POP()) ? true : false;
	vms->c.vm_ip++;
	break;

      NUMOP(OP_GT, vms->r->vm_acc = (NUM(vms->r->vm_acc) < NUM(POP())) ? true : false);
      NUMOP(OP_LT, vms->r->vm_acc = (NUM(vms->r->vm_acc) > NUM(POP())) ? true : false);
      NUMOP(OP_GE, vms->r->vm_acc = (NUM(vms->r->vm_acc) <= NUM(POP())) ? true : false);
      NUMOP(OP_LE, vms->r->vm_acc = (NUM(vms->r->vm_acc) >= NUM(POP())) ? true : false);

      NUMOP(OP_NEG, vms->r->vm_acc = MKNUM(-NUM(vms->r->vm_acc)));
      NUMOP(OP_BNOT, vms->r->vm_acc = MKNUM(~NUM(vms->r->vm_acc)));
      NUMOP(OP_BOR, vms->r->vm_acc = MKNUM(NUM(vms->r->vm_acc)|NUM(POP())));
      NUMOP(OP_BAND, vms->r->vm_acc = MKNUM(NUM(vms->r->vm_acc)&NUM(POP())));

      case OP_PLUS:
	if (vms->r->vm_acc == NULL || PEEK() == NULL) {
	  vm_raise(vms, (OBJ) newsym("vm-runtime-type-error"), vms->r->vm_acc);
	  break;
	}
	if (NUMP(vms->r->vm_acc) && NUMP(PEEK()))
	  vms->r->vm_acc = MKNUM(NUM(vms->r->vm_acc)+NUM(POP()));
	else if (TAGGEDP(vms->r->vm_acc) || TAGGEDP(PEEK())) {
	  vm_raise(vms, (OBJ) newsym("vm-runtime-type-error"), vms->r->vm_acc);
	  break;
	} else if (BVECTORP(vms->r->vm_acc) && BVECTORP(PEEK()))
	  vms->r->vm_acc = (OBJ) bvector_concat((BVECTOR) POP(), (BVECTOR) vms->r->vm_acc);
	else if (VECTORP(vms->r->vm_acc) && VECTORP(PEEK()))
	  vms->r->vm_acc = (OBJ) vector_concat((VECTOR) POP(), (VECTOR) vms->r->vm_acc);
	else {
	  vm_raise(vms, (OBJ) newsym("vm-runtime-type-error"), vms->r->vm_acc);
	  break;
	}
	vms->c.vm_ip++;
	break;

      NUMOP(OP_MINUS, vms->r->vm_acc = MKNUM(NUM(POP())-NUM(vms->r->vm_acc)));
      NUMOP(OP_STAR, vms->r->vm_acc = MKNUM(NUM(POP())*NUM(vms->r->vm_acc)));
      NUMOP(OP_SLASH,
	    if (vms->r->vm_acc == MKNUM(0))
	      vm_raise(vms, (OBJ) newsym("divide-by-zero"), NULL);
	    else
	      vms->r->vm_acc = MKNUM(NUM(POP())/NUM(vms->r->vm_acc)));
      NUMOP(OP_PERCENT,
	    if (vms->r->vm_acc == MKNUM(0))
	      vm_raise(vms, (OBJ) newsym("divide-by-zero"), NULL);
	    else
	      vms->r->vm_acc = MKNUM(NUM(POP())%NUM(vms->r->vm_acc)));

      default:
	fprintf(stderr, "Unknown bytecode reached (%d == 0x%x).\n",
		CODEAT(vms->c.vm_ip),
		CODEAT(vms->c.vm_ip));
	exit(MOVE_EXIT_PROGRAMMER_FUCKUP);
    }
  }

  return vms->c.vm_state == VM_STATE_DYING;
}