Пример #1
0
Value VM::run(Value fv, int nArg, Value *args) {
    static const int nExtra = 1;
    Stack stack;
    Value *regs = stack.maybeGrow(0, nArg + nExtra + 1);
    regs[0] = fv;
    Value *base = regs + nExtra;
    base[0] = VNIL;
    memcpy(base+1, args, nArg * sizeof(Value));
    Func *activeFunc = 0; // no active func
    int err = DO_CALL(fv, nArg, regs, base, &stack);    
    return !err ? base[0] : VNIL;
}
Пример #2
0
// extern __thread jmp_buf jumpBuf;
int VM::call(Value A, int nEffArgs, Value *regs, Stack *stack) {
    Vector<RetInfo> retInfo; // only used if FAST_CALL

    if (!(IS_O_TYPE(A, O_FUNC) || IS_CF(A) || IS_O_TYPE(A, O_CFUNC))) { return -1; }
    regs  = stack->maybeGrow(regs, 256);
    int nExpectedArgs = IS_O_TYPE(A, O_FUNC) ? ((Func *)GET_OBJ(A))->proto->nArgs : NARGS_CFUNC;
    nEffArgs = prepareStackForCall(regs, nExpectedArgs, nEffArgs, gc);

    if (IS_CF(A) || IS_O_TYPE(A, O_CFUNC)) {
        if (IS_CF(A)) {
            tfunc f = GET_CF(A);
            *regs = f(this, CFunc::CFUNC_CALL, 0, regs, nEffArgs);
        } else {
            ((CFunc *) GET_OBJ(A))->call(this, regs, nEffArgs);
        }
        return 0;
    }

    unsigned code = 0;
    Value B;
    Value *ptrC;
    Func *activeFunc = (Func *) GET_OBJ(A);
    unsigned *pc = (unsigned *) activeFunc->proto->code.buf();

    static void *dispatch[] = {
#define _(name) &&name
#include "opcodes.inc"
#undef _
    };

    assert(sizeof(dispatch)/sizeof(dispatch[0]) == N_OPCODES);

    copyUpvals(activeFunc, regs);

    STEP;

 JMP:  pc += OD(code);    STEP;
 JT:   if (!IS_FALSE(*ptrC)) { pc += OD(code);  } STEP;
 JF:   if ( IS_FALSE(*ptrC)) { pc += OD(code);  } STEP;
 JLT:  if (lessThan(A, B))   { pc += OSC(code); } STEP;
 JNIS: if (A != B)           { pc += OSC(code); } STEP;

 FOR: 
    A = *(ptrC + 1);
    B = *(ptrC + 2);
    if (!IS_NUM(A) || !IS_NUM(B)) { goto error; } // E_FOR_NOT_NUMBER
    *ptrC = B;
    if (!(GET_NUM(B) < GET_NUM(A))) { pc += OD(code); }
    STEP;

 LOOP: {
        const double counter = GET_NUM(*ptrC) + 1;
        if (counter < GET_NUM(*(ptrC+1))) { pc += OD(code); }
        *ptrC = VAL_NUM(counter);
        STEP;
    }

 FUNC:
    assert(IS_PROTO(A));
    *ptrC = VAL_OBJ(Func::alloc(gc, PROTO(A), regs + 256, regs, OB(code)));
    STEP;

    // index, A[B]
 GETI: *ptrC = types->type(A)->indexGet(A, B); if (*ptrC == VERR) { goto error; } STEP;
 GETF: *ptrC = types->type(A)->fieldGet(A, B); if (*ptrC == VERR) { goto error; } STEP;
    
 SETI: if (!types->type(*ptrC)->indexSet(*ptrC, A, B)) { goto error; } STEP;
 SETF: if (!types->type(*ptrC)->fieldSet(*ptrC, A, B)) { goto error; } STEP;
    /*
      const int oa = OA(code);
      const int ob = OB(code);
      int top = max(oa, ob) + 1;
      top = max(top, activeFunc->proto->localsTop);
      Value *base = regs + top;
      printf("top %d\n", top);
      base[0] = A;
      base[1] = B;
      int cPos = ptrC - regs;
      DO_CALL(v, 2, regs, base, stack);
      regs[cPos] = base[0];
      break;
      if (*ptrC == VERR) { goto error; }
    */
        
 GETS: *ptrC = getSlice(gc, A, B, regs[OB(code)+1]); if (*ptrC==VERR) { goto error; } STEP;
 SETS: if (setSlice(*ptrC, A, regs[OA(code)+1], B)) { goto error; } STEP;

 RET: {
        regs[0] = A;
        Value *root = stack->base;
        gc->maybeCollect(root, regs - root + 1);
#if FAST_CALL
        if (!retInfo.size()) {
            return 0;
        }
        RetInfo *ri = retInfo.top();
        pc         = ri->pc;
        regs       = stack->base + ri->base;
        activeFunc = ri->func;
        retInfo.pop();
        copyUpvals(activeFunc, regs);
        STEP;
#else
        return 0;
#endif
    }

CALL: { 
        if (!IS_OBJ(A) && !IS_CF(A)) { goto error; } // E_CALL_NOT_FUNC
        int nEffArgs = OSB(code);
        assert(nEffArgs != 0);
        Value *base = ptrC;
#if FAST_CALL
        if (IS_O_TYPE(A, O_FUNC)) {
            Func *f = (Func *) GET_OBJ(A);
            Proto *proto = f->proto;
            prepareStackForCall(base, proto->nArgs, nEffArgs, gc);
            RetInfo *ret = retInfo.push();
            ret->pc    = pc;
            ret->base  = regs - stack->base;
            ret->func  = activeFunc;
            regs = stack->maybeGrow(base, 256);
            copyUpvals(f, regs);
            pc   = proto->code.buf();
            activeFunc = f;
        } else {
#endif
            int ret = DO_CALL(A, nEffArgs, regs, base, stack);
            if (ret) { goto error; }
#if FAST_CALL
        }
#endif
        STEP;
    }
    
 MOVEUP: {
        const int slot = regs + 256 - ptrC;
        activeFunc->setUp(slot, A);
    }
    
 MOVE_R: *ptrC = A; STEP;
 MOVE_I: *ptrC = VAL_NUM(OD(code)); STEP;
 MOVE_V: {
        int id = OA(code);
        *ptrC =
            id == CONST_NIL          ? VNIL :
            id == CONST_EMPTY_STRING ? EMPTY_STRING :
            id == CONST_EMPTY_ARRAY  ? VAL_OBJ(emptyArray->copy(gc)) :
            VAL_OBJ(emptyMap->copy(gc));
        STEP;
    }
    
 MOVE_C: {
        Value v = *pc | (((u64) *(pc+1)) << 32);
        pc += 2;
        if (IS_ARRAY(v)) {
            v = VAL_OBJ(ARRAY(v)->copy(gc));
        } else if (IS_MAP(v)) {
            v = VAL_OBJ(MAP(v)->copy(gc));
        }
        *ptrC = v;
        STEP;
    }
 LEN:    *ptrC = VAL_NUM(len(A)); STEP;
 NOTL:   *ptrC = IS_FALSE(A) ? TRUE : FALSE; STEP;
    // notb: *ptrC = IS_INT(A)? VAL_INT(~getInteger(A)):ERROR(E_WRONG_TYPE); STEP;

 ADD: *ptrC = doAdd(gc, A, B); if (*ptrC == VERR) { goto error; } STEP;
 SUB: *ptrC = BINOP(-, A, B); STEP;
 MUL: *ptrC = BINOP(*, A, B); STEP;
 DIV: *ptrC = BINOP(/, A, B); STEP;
 MOD: *ptrC = doMod(A, B); if (*ptrC == VERR) { goto error; } STEP;
 POW: *ptrC = doPow(A, B); if (*ptrC == VERR) { goto error; } STEP;

 AND: *ptrC = BITOP(&,  A, B); STEP;
 OR:  *ptrC = BITOP(|,  A, B); STEP;
 XOR: *ptrC = BITOP(^,  A, B); STEP;

 SHL_RR: ERR(!IS_NUM(B), E_WRONG_TYPE); *ptrC = doSHL(A, (int)GET_NUM(B)); STEP;
 SHR_RR: ERR(!IS_NUM(B), E_WRONG_TYPE); *ptrC = doSHR(A, (int)GET_NUM(B)); STEP;
 SHL_RI: *ptrC = doSHL(A, OSB(code));       STEP;
 SHR_RI: *ptrC = doSHR(A, OSB(code));       STEP;

 EQ:  *ptrC = equals(A, B)  ? TRUE : FALSE; STEP;
 NEQ: *ptrC = !equals(A, B) ? TRUE : FALSE; STEP;
 IS:  *ptrC = A == B ? TRUE : FALSE; STEP;
 NIS: *ptrC = A != B ? TRUE : FALSE; STEP;

 LT:  *ptrC = lessThan(A, B) ? TRUE : FALSE; STEP;
 LE:  *ptrC = (equals(A, B) || lessThan(A, B)) ? TRUE : FALSE; STEP;

 error: return pc - (unsigned *) activeFunc->proto->code.buf();
}
Пример #3
0
int32_t syscall(int32_t number, ...) {

    int32_t *arg = &number;
    int32_t ret;

    switch (number) {
        case SYS_MOUNT:     {ret=DO_CALL(mount            ); break;}
        case SYS_UMOUNT:    {ret=DO_CALL(umount           ); break;}
        case SYS_MKNOD:     {ret=DO_CALL(mknod            ); break;}
        case SYS_RENAME:    {ret=DO_CALL(rename           ); break;}
        case SYS_LINK:      {ret=DO_CALL(link             ); break;}
        case SYS_UNLINK:    {ret=DO_CALL(unlink           ); break;}
        case SYS_MKDIR:     {ret=DO_CALL(mkdir            ); break;}
        case SYS_RMDIR:     {ret=DO_CALL(rmdir            ); break;}
        case SYS_OPEN:      {ret=DO_CALL(open             ); break;}
        case SYS_CLOSE:     {ret=DO_CALL(close            ); break;}
        case SYS_CHDIR:     {ret=DO_CALL(chdir            ); break;}
        case SYS_GETCWD:    {ret=DO_CALL(getcwd           ); break;}
        case SYS_TRUNCATE:  {ret=DO_CALL(truncate         ); break;}
        case SYS_FTRUNCATE: {ret=DO_CALL(ftruncate        ); break;}
        case SYS_READ:      {ret=DO_CALL(read             ); break;}
        case SYS_WRITE:     {ret=DO_CALL(write            ); break;}
        case SYS_SEEK:      {ret=DO_CALL(seek             ); break;}
        case SYS_READDIR:   {ret=DO_CALL(readdir          ); break;}
        case SYS_STAT:      {ret=DO_CALL(stat             ); break;}
        case SYS_FSTAT:     {ret=DO_CALL(fstat            ); break;}
        case SYS_STATFS:    {ret=DO_CALL(statfs           ); break;}
        case SYS_FSTATFS:   {ret=DO_CALL(fstatfs          ); break;}
        case SYS_DUP:       {ret=DO_CALL(dup              ); break;}
        case SYS_DUP2:      {ret=DO_CALL(dup2             ); break;}
        case SYS_IOCTL:     {ret=DO_CALL(ioctl            ); break;}
        case SYS_EXECVE:    {ret=DO_CALL(execve           ); break;}
        case SYS_FORK:      {ret=DO_CALL(fork             ); break;}
        case SYS_WAITPID:   {ret=DO_CALL(waitpid          ); break;}
        case SYS_EXIT:      {ret=DO_CALL(exit             ); break;}
        case SYS_BRK:       {ret=DO_CALL(brk              ); break;}
        case SYS_MMAP:      {ret=DO_CALL2(mmap, mmap_arg_t); break;}
        case SYS_SEND:      {ret=DO_CALL(send             ); break;}
        case SYS_RECEIVE:   {ret=DO_CALL(receive          ); break;}
        case SYS_GETPID:    {ret=DO_CALL(getpid           ); break;}
        case SYS_REBOOT:    {ret=DO_CALL(legacy_reboot    ); break;}
        case SYS_MUNMAP:    {ret=DO_CALL(munmap           ); break;}
        default:            {ret=-EINVAL                   ; break;}
    }

    return ret;

}