Example #1
0
VMFrameStack::~VMFrameStack()
{
	while (PopFrame() != NULL)
	{ }
	if (Blocks != NULL)
	{
		BlockHeader *block, *next;
		for (block = Blocks; block != NULL; block = next)
		{
			next = block->NextBlock;
			delete[] (VM_UBYTE *)block;
		}
		Blocks = NULL;
	}
	if (UnusedBlocks != NULL)
	{
		BlockHeader *block, *next;
		for (block = UnusedBlocks; block != NULL; block = next)
		{
			next = block->NextBlock;
			delete[] (VM_UBYTE *)block;
		}
		UnusedBlocks = NULL;
	}
}
Example #2
0
int VMFrameStack::Call(VMFunction *func, VMValue *params, int numparams, VMReturn *results, int numresults, VMException **trap)
{
	bool allocated = false;
	try
	{
		if (func->Native)
		{
			return static_cast<VMNativeFunction *>(func)->NativeCall(this, params, numparams, results, numresults);
		}
		else
		{
			AllocFrame(static_cast<VMScriptFunction *>(func));
			allocated = true;
			VMFillParams(params, TopFrame(), numparams);
			int numret = VMExec(this, static_cast<VMScriptFunction *>(func)->Code, results, numresults);
			PopFrame();
			return numret;
		}
	}
	catch (VMException *exception)
	{
		if (allocated)
		{
			PopFrame();
		}
		if (trap != NULL)
		{
			*trap = exception;
			return -1;
		}
		throw;
	}
	catch (...)
	{
		if (allocated)
		{
			PopFrame();
		}
		throw;
	}
}
Example #3
0
void CObjectOStream::HandleEOF(CEofException&)
{
    PopFrame();
    throw;
}
Example #4
0
int VMCall(VMFunction *func, VMValue *params, int numparams, VMReturn *results, int numresults/*, VMException **trap*/)
{
	bool allocated = false;
	try
	{	
		if (func->VarFlags & VARF_Native)
		{
			return static_cast<VMNativeFunction *>(func)->NativeCall(params, func->DefaultArgs, numparams, results, numresults);
		}
		else
		{
			auto code = static_cast<VMScriptFunction *>(func)->Code;
			// handle empty functions consisting of a single return explicitly so that empty virtual callbacks do not need to set up an entire VM frame.
			// code cann be null here in case of some non-fatal DECORATE errors.
			if (code == nullptr || code->word == (0x00808000|OP_RET))
			{
				return 0;
			}
			else if (code->word == (0x00048000|OP_RET))
			{
				if (numresults == 0) return 0;
				results[0].SetInt(static_cast<VMScriptFunction *>(func)->KonstD[0]);
				return 1;
			}
			else
			{
				VMCycles[0].Clock();
				VMCalls[0]++;
				auto &stack = GlobalVMStack;
				stack.AllocFrame(static_cast<VMScriptFunction *>(func));
				allocated = true;
				VMFillParams(params, stack.TopFrame(), numparams);
				int numret = VMExec(&stack, code, results, numresults);
				stack.PopFrame();
				VMCycles[0].Unclock();
				return numret;
			}
		}
	}
#if 0
	catch (VMException *exception)
	{
		if (allocated)
		{
			PopFrame();
		}
		if (trap != NULL)
		{
			*trap = exception;
			return -1;
		}
		throw;
	}
#endif
	catch (...)
	{
		if (allocated)
		{
			GlobalVMStack.PopFrame();
		}
		throw;
	}
}
Example #5
0
/* Execute - execute the main code */
int Execute(System *sys, ObjHeap *heap, VMHANDLE main)
{
    size_t stackSize;
    Interpreter *i;
    VMVALUE tmp, tmp2, ind;
    VMHANDLE obj, htmp;
    int8_t tmpb;

    /* allocate the interpreter state */
    if (!(i = (Interpreter *)AllocateFreeSpace(sys, sizeof(Interpreter))))
        return VMFALSE;

    /* make sure there is space left for the stack */
    if ((stackSize = (sys->freeTop - sys->freeNext) / sizeof(VMVALUE)) <= 0)
        return VMFALSE;
        
    /* setup the heap before/after compact functions */
    heap->beforeCompact = NULL;
    heap->afterCompact = AfterCompact;
    heap->compactCookie = i;
    
    /* initialize the interpreter state */
    i->sys = sys;
    i->heap = heap;
    i->stack = (VMVALUE *)((uint8_t *)i + sizeof(Interpreter));
    i->stackTop = i->stack + stackSize;
    
    /* setup to execute the main function */
    i->code = main;
    ObjAddRef(i->code);
    i->cbase = i->pc = GetCodePtr(main);
    i->sp = i->fp = i->stackTop;
    i->hsp = i->hfp = (VMHANDLE *)i->stack - 1;

    if (setjmp(i->sys->errorTarget)) {
        while (i->hsp > (VMHANDLE *)i->stack)
            ObjRelease(i->heap, PopH(i));
        ObjRelease(i->heap, i->code);
        return VMFALSE;
    }

    for (;;) {
#if 0
        ShowStack(i);
        DecodeInstruction(0, 0, i->pc);
#endif
        switch (VMCODEBYTE(i->pc++)) {
        case OP_HALT:
            return VMTRUE;
        case OP_BRT:
            get_VMVALUE(tmp, VMCODEBYTE(i->pc++));
            if (Pop(i))
                i->pc += tmp;
            break;
        case OP_BRTSC:
            get_VMVALUE(tmp, VMCODEBYTE(i->pc++));
            if (*i->sp)
                i->pc += tmp;
            else
                Drop(i, 1);
            break;
        case OP_BRF:
            get_VMVALUE(tmp, VMCODEBYTE(i->pc++));
            if (!Pop(i))
                i->pc += tmp;
            break;
        case OP_BRFSC:
            get_VMVALUE(tmp, VMCODEBYTE(i->pc++));
            if (!*i->sp)
                i->pc += tmp;
            else
                Drop(i, 1);
            break;
        case OP_BR:
            get_VMVALUE(tmp, VMCODEBYTE(i->pc++));
            i->pc += tmp;
            break;
        case OP_NOT:
            *i->sp = (*i->sp ? VMFALSE : VMTRUE);
            break;
        case OP_NEG:
            *i->sp = -*i->sp;
            break;
        case OP_ADD:
            tmp = Pop(i);
            *i->sp += tmp;
            break;
        case OP_SUB:
            tmp = Pop(i);
            *i->sp -= tmp;
            break;
        case OP_MUL:
            tmp = Pop(i);
            *i->sp *= tmp;
            break;
        case OP_DIV:
            tmp = Pop(i);
            *i->sp = (tmp == 0 ? 0 : *i->sp / tmp);
            break;
        case OP_REM:
            tmp = Pop(i);
            *i->sp = (tmp == 0 ? 0 : *i->sp % tmp);
            break;
        case OP_CAT:
            StringCat(i);
            break;
        case OP_BNOT:
            *i->sp = ~*i->sp;
            break;
        case OP_BAND:
            tmp = Pop(i);
            *i->sp &= tmp;
            break;
        case OP_BOR:
            tmp = Pop(i);
            *i->sp |= tmp;
            break;
        case OP_BXOR:
            tmp = Pop(i);
            *i->sp ^= tmp;
            break;
        case OP_SHL:
            tmp = Pop(i);
            *i->sp <<= tmp;
            break;
        case OP_SHR:
            tmp = Pop(i);
            *i->sp >>= tmp;
            break;
        case OP_LT:
            tmp = Pop(i);
            *i->sp = (*i->sp < tmp ? VMTRUE : VMFALSE);
            break;
        case OP_LE:
            tmp = Pop(i);
            *i->sp = (*i->sp <= tmp ? VMTRUE : VMFALSE);
            break;
        case OP_EQ:
            tmp = Pop(i);
            *i->sp = (*i->sp == tmp ? VMTRUE : VMFALSE);
            break;
        case OP_NE:
            tmp = Pop(i);
            *i->sp = (*i->sp != tmp ? VMTRUE : VMFALSE);
            break;
        case OP_GE:
            tmp = Pop(i);
            *i->sp = (*i->sp >= tmp ? VMTRUE : VMFALSE);
            break;
        case OP_GT:
            tmp = Pop(i);
            *i->sp = (*i->sp > tmp ? VMTRUE : VMFALSE);
            break;
        case OP_LIT:
            get_VMVALUE(tmp, VMCODEBYTE(i->pc++));
            CPush(i, tmp);
            break;
        case OP_GREF:
            get_VMVALUE(tmp, VMCODEBYTE(i->pc++));
            obj = (VMHANDLE)tmp;
            CPush(i, GetSymbolPtr(obj)->v.iValue);
            break;
        case OP_GSET:
            get_VMVALUE(tmp, VMCODEBYTE(i->pc++));
            obj = (VMHANDLE)tmp;
            GetSymbolPtr(obj)->v.iValue = Pop(i);
            break;
        case OP_LREF:
            tmpb = (int8_t)VMCODEBYTE(i->pc++);
            CPush(i, i->fp[(int)tmpb]);
            break;
        case OP_LSET:
            tmpb = (int8_t)VMCODEBYTE(i->pc++);
            i->fp[(int)tmpb] = Pop(i);
            break;
        case OP_VREF:
            ind = *i->sp;
            obj = *i->hsp;
            if (ind < 0 || ind >= GetHeapObjSize(obj))
                Abort(i->sys, str_subscript_err, ind);
            *i->sp = GetIntegerVectorBase(obj)[ind];
            DropH(i, 1);
            break;
        case OP_VSET:
            tmp2 = Pop(i);
            ind = Pop(i);
            obj = *i->hsp;
            if (ind < 0 || ind >= GetHeapObjSize(obj))
                Abort(i->sys, str_subscript_err, ind);
            GetIntegerVectorBase(obj)[ind] = tmp2;
            DropH(i, 1);
            break;
       case OP_LITH:
            get_VMVALUE(tmp, VMCODEBYTE(i->pc++));
            CPushH(i, (VMHANDLE)tmp);
            ObjAddRef(*i->hsp);
            break;
        case OP_GREFH:
            get_VMVALUE(tmp, VMCODEBYTE(i->pc++));
            CPushH(i, GetSymbolPtr((VMHANDLE)tmp)->v.hValue);
            ObjAddRef(*i->hsp);
            break;
        case OP_GSETH:
            get_VMVALUE(tmp, VMCODEBYTE(i->pc++));
            ObjRelease(i->heap, GetSymbolPtr((VMHANDLE)tmp)->v.hValue);
            GetSymbolPtr((VMHANDLE)tmp)->v.hValue = PopH(i);
            break;
        case OP_LREFH:
            tmpb = (int8_t)VMCODEBYTE(i->pc++);
            CPushH(i, i->hfp[(int)tmpb]);
            ObjAddRef(*i->hsp);
            break;
        case OP_LSETH:
            tmpb = (int8_t)VMCODEBYTE(i->pc++);
            ObjRelease(i->heap, i->hfp[(int)tmpb]);
            i->hfp[(int)tmpb] = PopH(i);
            break;
        case OP_VREFH:
            ind = Pop(i);
            obj = *i->hsp;
            if (ind < 0 || ind >= GetHeapObjSize(obj))
                Abort(i->sys, str_subscript_err, ind);
            *i->hsp = GetStringVectorBase(obj)[ind];
            ObjAddRef(*i->hsp);
            break;
        case OP_VSETH:
            htmp = PopH(i);
            ind = Pop(i);
            obj = *i->hsp;
            if (ind < 0 || ind >= GetHeapObjSize(obj))
                Abort(i->sys, str_subscript_err, ind);
            ObjRelease(i->heap, GetStringVectorBase(obj)[ind]);
            GetStringVectorBase(obj)[ind] = htmp;
            DropH(i, 1);
            break;
        case OP_RESERVE:
            tmp = VMCODEBYTE(i->pc++);
            tmp2 = VMCODEBYTE(i->pc++);
            Reserve(i, tmp);
            ReserveH(i, tmp2);
            break;
         case OP_CALL:
            StartCode(i);
            break;
        case OP_RETURN:
            tmp = *i->sp;
            PopFrame(i);
            Push(i, tmp);
            break;
        case OP_RETURNH:
            htmp = *i->hsp;
            PopFrame(i);
            PushH(i, htmp);
            break;
        case OP_RETURNV:
            PopFrame(i);
            break;
        case OP_DROP:
            Drop(i, 1);
            break;
        case OP_DROPH:
            ObjRelease(i->heap, *i->hsp);
            DropH(i, 1);
            break;
        default:
            Abort(i->sys, str_opcode_err, VMCODEBYTE(i->pc - 1));
            break;
        }
    }
}
Example #6
0
int VMFrameStack::Call(VMFunction *func, VMValue *params, int numparams, VMReturn *results, int numresults, VMException **trap)
{
	bool allocated = false;
	try
	{
		if (func->Native)
		{
			return static_cast<VMNativeFunction *>(func)->NativeCall(this, params, numparams, results, numresults);
		}
		else
		{
			AllocFrame(static_cast<VMScriptFunction *>(func));
			allocated = true;
			VMFillParams(params, TopFrame(), numparams);
			int numret = VMExec(this, static_cast<VMScriptFunction *>(func)->Code, results, numresults);
			PopFrame();
			return numret;
		}
	}
	catch (VMException *exception)
	{
		if (allocated)
		{
			PopFrame();
		}
		if (trap != NULL)
		{
			*trap = exception;
			return -1;
		}
		throw;
	}
	catch (EVMAbortException exception)
	{
		if (allocated)
		{
			PopFrame();
		}
		if (trap != nullptr)
		{
			*trap = nullptr;
		}

		Printf("VM execution aborted: ");
		switch (exception)
		{
		case X_READ_NIL:
			Printf("tried to read from address zero.");
			break;

		case X_WRITE_NIL:
			Printf("tried to write to address zero.");
			break;

		case X_TOO_MANY_TRIES:
			Printf("too many try-catch blocks.");
			break;

		case X_ARRAY_OUT_OF_BOUNDS:
			Printf("array access out of bounds.");
			break;

		case X_DIVISION_BY_ZERO:
			Printf("division by zero.");
			break;

		case X_BAD_SELF:
			Printf("invalid self pointer.");
			break;
		}
		Printf("\n");

		return -1;
	}
	catch (...)
	{
		if (allocated)
		{
			PopFrame();
		}
		throw;
	}
}