mirror of
https://github.com/ZDoom/qzdoom.git
synced 2025-05-31 17:10:51 +00:00
- allow the VM to run on one global stack per thread.
It is utterly pointless to require every function that wants to make a VM call to allocate a new stack first. The allocation overhead doubles the time to set up the call. With one stack, previously allocated memory can be reused. The only important thing is, if this ever gets used in a multithreaded environment to have the stack being declared as thread_local, although for ZDoom this is of no consequence. - eliminated all cases where native code was calling other native code through the VM interface. After scriptifying the game code, only 5 places were left which were quickly eliminated. This was mostly to ensure that the native VM function parameters do not need to be propagated further than absolutely necessary.
This commit is contained in:
parent
47884f8a71
commit
86544086df
23 changed files with 176 additions and 229 deletions
|
@ -4228,7 +4228,7 @@ PPrototype *FxTypeCheck::ReturnProto()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
int BuiltinTypeCheck(VMFrameStack *stack, VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret)
|
||||
int BuiltinTypeCheck(VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret)
|
||||
{
|
||||
assert(numparam == 2);
|
||||
PARAM_POINTER_AT(0, obj, DObject);
|
||||
|
@ -5030,7 +5030,7 @@ FxExpression *FxRandom::Resolve(FCompileContext &ctx)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
int BuiltinRandom(VMFrameStack *stack, VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret)
|
||||
int BuiltinRandom(VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret)
|
||||
{
|
||||
assert(numparam >= 1 && numparam <= 3);
|
||||
FRandom *rng = reinterpret_cast<FRandom *>(param[0].a);
|
||||
|
@ -5284,7 +5284,7 @@ FxFRandom::FxFRandom(FRandom *r, FxExpression *mi, FxExpression *ma, const FScri
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
int BuiltinFRandom(VMFrameStack *stack, VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret)
|
||||
int BuiltinFRandom(VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret)
|
||||
{
|
||||
assert(numparam == 1 || numparam == 3);
|
||||
FRandom *rng = reinterpret_cast<FRandom *>(param[0].a);
|
||||
|
@ -7558,7 +7558,7 @@ FxExpression *FxActionSpecialCall::Resolve(FCompileContext& ctx)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
int BuiltinCallLineSpecial(VMFrameStack *stack, VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret)
|
||||
int BuiltinCallLineSpecial(VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret)
|
||||
{
|
||||
assert(numparam > 2 && numparam < 8);
|
||||
assert(param[0].Type == REGT_INT);
|
||||
|
@ -9518,7 +9518,7 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
int BuiltinNameToClass(VMFrameStack *stack, VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret)
|
||||
int BuiltinNameToClass(VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret)
|
||||
{
|
||||
assert(numparam == 2);
|
||||
assert(numret == 1);
|
||||
|
@ -9650,7 +9650,7 @@ FxExpression *FxClassPtrCast::Resolve(FCompileContext &ctx)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
int BuiltinClassCast(VMFrameStack *stack, VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret)
|
||||
int BuiltinClassCast(VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_CLASS(from, DObject);
|
||||
|
|
|
@ -867,7 +867,7 @@ class VMNativeFunction : public VMFunction
|
|||
{
|
||||
DECLARE_CLASS(VMNativeFunction, VMFunction);
|
||||
public:
|
||||
typedef int (*NativeCallType)(VMFrameStack *stack, VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret);
|
||||
typedef int (*NativeCallType)(VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret);
|
||||
|
||||
VMNativeFunction() : NativeCall(NULL) { Native = true; }
|
||||
VMNativeFunction(NativeCallType call) : NativeCall(call) { Native = true; }
|
||||
|
@ -930,6 +930,9 @@ enum EVMEngine
|
|||
VMEngine_Checked
|
||||
};
|
||||
|
||||
extern thread_local VMFrameStack GlobalVMStack;
|
||||
|
||||
|
||||
void VMSelectEngine(EVMEngine engine);
|
||||
extern int (*VMExec)(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret);
|
||||
void VMFillParams(VMValue *params, VMFrame *callee, int numparam);
|
||||
|
@ -938,8 +941,8 @@ void VMDumpConstants(FILE *out, const VMScriptFunction *func);
|
|||
void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction *func);
|
||||
|
||||
// Use this in the prototype for a native function.
|
||||
#define VM_ARGS VMFrameStack *stack, VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret
|
||||
#define VM_ARGS_NAMES stack, param, defaultparam, numparam, ret, numret
|
||||
#define VM_ARGS VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret
|
||||
#define VM_ARGS_NAMES param, defaultparam, numparam, ret, numret
|
||||
|
||||
// Use these to collect the parameters in a native function.
|
||||
// variable name <x> at position <p>
|
||||
|
@ -1012,7 +1015,7 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
|
|||
#define PARAM_OBJECT_DEF(x,type) ++paramnum; PARAM_OBJECT_DEF_AT(paramnum,x,type)
|
||||
#define PARAM_CLASS_DEF(x,base) ++paramnum; PARAM_CLASS_DEF_AT(paramnum,x,base)
|
||||
|
||||
typedef int(*actionf_p)(VMFrameStack *stack, VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret);/*(VM_ARGS)*/
|
||||
typedef int(*actionf_p)(VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret);/*(VM_ARGS)*/
|
||||
|
||||
struct FieldDesc
|
||||
{
|
||||
|
@ -1048,7 +1051,6 @@ struct AFuncDesc
|
|||
|
||||
// Macros to handle action functions. These are here so that I don't have to
|
||||
// change every single use in case the parameters change.
|
||||
#define DECLARE_ACTION(name) extern VMNativeFunction *AActor_##name##_VMPtr;
|
||||
|
||||
#define DEFINE_ACTION_FUNCTION(cls, name) \
|
||||
static int AF_##cls##_##name(VM_ARGS); \
|
||||
|
@ -1090,8 +1092,6 @@ struct AFuncDesc
|
|||
MSVC_FSEG FieldDesc const *const VMField_##cls##_##scriptname##_HookPtr GCC_FSEG = &VMField_##cls##_##scriptname;
|
||||
|
||||
class AActor;
|
||||
void CallAction(VMFrameStack *stack, VMFunction *vmfunc, AActor *self);
|
||||
#define CALL_ACTION(name, self) CallAction(stack, AActor_##name##_VMPtr, self);
|
||||
|
||||
|
||||
#define ACTION_RETURN_STATE(v) do { FState *state = v; if (numret > 0) { assert(ret != NULL); ret->SetPointer(state, ATAG_STATE); return 1; } return 0; } while(0)
|
||||
|
|
|
@ -146,6 +146,12 @@ VMExec_Checked::Exec
|
|||
#endif
|
||||
;
|
||||
|
||||
// Note: If the VM is being used in multiple threads, this should be declared as thread_local.
|
||||
// ZDoom doesn't need this at the moment so this is disabled.
|
||||
|
||||
thread_local VMFrameStack GlobalVMStack;
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// VMSelectEngine
|
||||
|
|
|
@ -422,12 +422,13 @@ VMFrame *VMFrameStack::PopFrame()
|
|||
|
||||
int VMFrameStack::Call(VMFunction *func, VMValue *params, int numparams, VMReturn *results, int numresults, VMException **trap)
|
||||
{
|
||||
assert(this == VMGlobalStack); // why would anyone even want to create a local stack?
|
||||
bool allocated = false;
|
||||
try
|
||||
{
|
||||
if (func->Native)
|
||||
{
|
||||
return static_cast<VMNativeFunction *>(func)->NativeCall(this, params, func->DefaultArgs, numparams, results, numresults);
|
||||
return static_cast<VMNativeFunction *>(func)->NativeCall(params, func->DefaultArgs, numparams, results, numresults);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -503,11 +504,3 @@ int VMFrameStack::Call(VMFunction *func, VMValue *params, int numparams, VMRetur
|
|||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
class AActor;
|
||||
void CallAction(VMFrameStack *stack, VMFunction *vmfunc, AActor *self)
|
||||
{
|
||||
// Without the type cast this picks the 'void *' assignment...
|
||||
VMValue params[3] = { (DObject*)self, (DObject*)self, VMValue(nullptr, ATAG_GENERIC) };
|
||||
stack->Call(vmfunc, params, vmfunc->ImplicitArgs, nullptr, 0, nullptr);
|
||||
}
|
||||
|
|
|
@ -2362,7 +2362,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
|
|||
{
|
||||
if (vindex != -1)
|
||||
{
|
||||
Error(p, "Function %s attempts to override parent function without 'override' qualifier", FName(f->Name).GetChars());
|
||||
Error(f, "Function %s attempts to override parent function without 'override' qualifier", FName(f->Name).GetChars());
|
||||
}
|
||||
sym->Variants[0].Implementation->VirtualIndex = clstype->Virtuals.Push(sym->Variants[0].Implementation);
|
||||
}
|
||||
|
@ -3267,3 +3267,7 @@ FArgumentList &ZCCCompiler::ConvertNodeList(FArgumentList &args, ZCC_TreeNode *h
|
|||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
void func()
|
||||
{
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue