예제 #1
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;
	}
}
예제 #2
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;
	}
}
예제 #3
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;
	}
}