- implemented VMCallWithDefaults and used it for all calls with variable arguments.

This isn't used for the 3 action function calls because it requires an array allocation which would be a bit too costly for something as frequently called as action functions.
They will need a different approach.
This commit is contained in:
Christoph Oelckers 2018-11-16 19:18:33 +01:00
parent 6d7710165c
commit 97573a0452
6 changed files with 23 additions and 12 deletions

View file

@ -175,13 +175,13 @@ bool FState::CallAction(AActor *self, AActor *stateowner, FStateParamInfo *info,
if (stateret == nullptr) if (stateret == nullptr)
{ {
VMCallWithDefaults(ActionFunc, params, ActionFunc->ImplicitArgs, nullptr, 0); VMCallAction(ActionFunc, params, ActionFunc->ImplicitArgs, nullptr, 0);
} }
else else
{ {
VMReturn ret; VMReturn ret;
ret.PointerAt((void **)stateret); ret.PointerAt((void **)stateret);
VMCallWithDefaults(ActionFunc, params, ActionFunc->ImplicitArgs, &ret, 1); VMCallAction(ActionFunc, params, ActionFunc->ImplicitArgs, &ret, 1);
} }
} }
catch (CVMAbortException &err) catch (CVMAbortException &err)

View file

@ -477,7 +477,7 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc)
} }
DMenuItemBase *item = (DMenuItemBase*)cls->CreateNew(); DMenuItemBase *item = (DMenuItemBase*)cls->CreateNew();
params[0] = item; params[0] = item;
VMCallWithDefaults(func->Variants[0].Implementation, &params[0], params.Size(), nullptr, 0); VMCallWithDefaults(func->Variants[0].Implementation, params, nullptr, 0);
desc->mItems.Push((DMenuItemBase*)item); desc->mItems.Push((DMenuItemBase*)item);
if (cls->IsDescendantOf("ListMenuItemSelectable")) if (cls->IsDescendantOf("ListMenuItemSelectable"))
@ -917,7 +917,7 @@ static void ParseOptionMenuBody(FScanner &sc, DOptionMenuDescriptor *desc)
DMenuItemBase *item = (DMenuItemBase*)cls->CreateNew(); DMenuItemBase *item = (DMenuItemBase*)cls->CreateNew();
params[0] = item; params[0] = item;
VMCallWithDefaults(func->Variants[0].Implementation, &params[0], params.Size(), nullptr, 0); VMCallWithDefaults(func->Variants[0].Implementation, params, nullptr, 0);
desc->mItems.Push((DMenuItemBase*)item); desc->mItems.Push((DMenuItemBase*)item);
success = true; success = true;

View file

@ -5448,7 +5448,7 @@ static int ScriptCall(AActor *activator, unsigned argc, int32_t *args)
// The return value can be the same types as the parameter types, plus void // The return value can be the same types as the parameter types, plus void
if (func->Proto->ReturnTypes.Size() == 0) if (func->Proto->ReturnTypes.Size() == 0)
{ {
VMCallWithDefaults(func, &params[0], params.Size(), nullptr, 0); VMCallWithDefaults(func, params, nullptr, 0);
} }
else else
{ {
@ -5470,20 +5470,20 @@ static int ScriptCall(AActor *activator, unsigned argc, int32_t *args)
{ {
double d; double d;
VMReturn ret(&d); VMReturn ret(&d);
VMCallWithDefaults(func, &params[0], params.Size(), &ret, 1); VMCallWithDefaults(func, params, &ret, 1);
retval = DoubleToACS(d); retval = DoubleToACS(d);
} }
else if (rettype == TypeString) else if (rettype == TypeString)
{ {
FString d; FString d;
VMReturn ret(&d); VMReturn ret(&d);
VMCallWithDefaults(func, &params[0], params.Size(), &ret, 1); VMCallWithDefaults(func, params, &ret, 1);
retval = GlobalACSStrings.AddString(d); retval = GlobalACSStrings.AddString(d);
} }
else else
{ {
// All other return values can not be handled so ignore them. // All other return values can not be handled so ignore them.
VMCallWithDefaults(func, &params[0], params.Size(), nullptr, 0); VMCallWithDefaults(func, params, nullptr, 0);
} }
} }
} }

View file

@ -170,7 +170,7 @@ bool AStateProvider::CallStateChain (AActor *actor, FState *state)
try try
{ {
state->CheckCallerType(actor, this); state->CheckCallerType(actor, this);
VMCallWithDefaults(state->ActionFunc, params, state->ActionFunc->ImplicitArgs, wantret, numret); VMCallAction(state->ActionFunc, params, state->ActionFunc->ImplicitArgs, wantret, numret);
} }
catch (CVMAbortException &err) catch (CVMAbortException &err)
{ {

View file

@ -209,8 +209,6 @@ struct VMValue
const FString *sp; const FString *sp;
}; };
// Unfortunately, FString cannot be used directly.
// Fortunately, it is relatively simple.
const FString &s() const { return *sp; } const FString &s() const { return *sp; }
VMValue() VMValue()
@ -376,8 +374,9 @@ private:
}; };
int VMCall(VMFunction *func, VMValue *params, int numparams, VMReturn *results, int numresults/*, VMException **trap = NULL*/); int VMCall(VMFunction *func, VMValue *params, int numparams, VMReturn *results, int numresults/*, VMException **trap = NULL*/);
int VMCallWithDefaults(VMFunction *func, TArray<VMValue> &params, VMReturn *results, int numresults/*, VMException **trap = NULL*/);
inline int VMCallWithDefaults(VMFunction *func, VMValue *params, int numparams, VMReturn *results, int numresults/*, VMException **trap = NULL*/) inline int VMCallAction(VMFunction *func, VMValue *params, int numparams, VMReturn *results, int numresults/*, VMException **trap = NULL*/)
{ {
return VMCall(func, params, numparams, results, numresults); return VMCall(func, params, numparams, results, numresults);
} }

View file

@ -577,6 +577,18 @@ int VMCall(VMFunction *func, VMValue *params, int numparams, VMReturn *results,
#endif #endif
} }
int VMCallWithDefaults(VMFunction *func, TArray<VMValue> &params, VMReturn *results, int numresults/*, VMException **trap = NULL*/)
{
if (func->DefaultArgs.Size() > params.Size())
{
auto oldp = params.Size();
params.Resize(func->DefaultArgs.Size());
memcpy(&params[oldp], &func->DefaultArgs[oldp], (params.Size() - oldp) * sizeof(VMValue));
}
return VMCall(func, params.Data(), params.Size(), results, numresults);
}
// Exception stuff for the VM is intentionally placed there, because having this in vmexec.cpp would subject it to inlining // Exception stuff for the VM is intentionally placed there, because having this in vmexec.cpp would subject it to inlining
// which we do not want because it increases the local stack requirements of Exec which are already too high. // which we do not want because it increases the local stack requirements of Exec which are already too high.
FString CVMAbortException::stacktrace; FString CVMAbortException::stacktrace;