From 16053c7cdbd0a0283d2479a4814d217097f4d053 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 16 Nov 2018 20:38:52 +0100 Subject: [PATCH] - build full argument lists for action function calls. This uses one static global array to avoid frequent reallocations. --- src/info.cpp | 31 ++++++++++++++++++++++++------- src/p_actionfunctions.cpp | 29 ++++++++++++++++++++++++++--- src/tarray.h | 23 ++++++++++++++++++++--- 3 files changed, 70 insertions(+), 13 deletions(-) diff --git a/src/info.cpp b/src/info.cpp index 402f74c37f..385dc5bd47 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -148,6 +148,7 @@ void FState::CheckCallerType(AActor *self, AActor *stateowner) } } +TArray actionParams; bool FState::CallAction(AActor *self, AActor *stateowner, FStateParamInfo *info, FState **stateret) { @@ -155,7 +156,6 @@ bool FState::CallAction(AActor *self, AActor *stateowner, FStateParamInfo *info, { ActionCycles.Clock(); - VMValue params[3] = { self, stateowner, VMValue(info) }; // If the function returns a state, store it at *stateret. // If it doesn't return a state but stateret is non-nullptr, we need // to set *stateret to nullptr. @@ -169,19 +169,36 @@ bool FState::CallAction(AActor *self, AActor *stateowner, FStateParamInfo *info, stateret = nullptr; } } + + VMReturn ret; + ret.PointerAt((void **)stateret); try { CheckCallerType(self, stateowner); - - if (stateret == nullptr) + + // Build the parameter array. Action functions have never any explicit parameters but need to pass the defaults + // and fill in the implicit arguments of the called function. + + if (ActionFunc->DefaultArgs.Size() > 0) { - VMCallAction(ActionFunc, params, ActionFunc->ImplicitArgs, nullptr, 0); + auto index = actionParams.Append(ActionFunc->DefaultArgs); + if (ActionFunc->ImplicitArgs >= 1) + { + actionParams[index] = self; + } + if (ActionFunc->ImplicitArgs == 3) + { + actionParams[index + 1] = stateowner; + actionParams[index + 2] = VMValue(info); + } + + VMCallAction(ActionFunc, &actionParams[index], ActionFunc->DefaultArgs.Size(), &ret, stateret != nullptr); + actionParams.Clamp(index); } else { - VMReturn ret; - ret.PointerAt((void **)stateret); - VMCallAction(ActionFunc, params, ActionFunc->ImplicitArgs, &ret, 1); + VMValue params[3] = { self, stateowner, VMValue(info) }; + VMCallAction(ActionFunc, params, ActionFunc->ImplicitArgs, &ret, stateret != nullptr); } } catch (CVMAbortException &err) diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 7bb55b6fb1..aa722ba7ad 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -96,12 +96,13 @@ static FRandom pr_bfgselfdamage("BFGSelfDamage"); // until there is no next state // //========================================================================== +extern TArray actionParams; // this can use the same storage as CallAction + bool AStateProvider::CallStateChain (AActor *actor, FState *state) { INTBOOL result = false; int counter = 0; - VMValue params[3] = { actor, this, 0 }; // We accept return types of `state`, `(int|bool)` or `state, (int|bool)`. // The last one is for the benefit of A_Warp and A_Teleport. @@ -139,7 +140,6 @@ bool AStateProvider::CallStateChain (AActor *actor, FState *state) VMReturn *wantret; FStateParamInfo stp = { state, STATE_StateChain, PSP_WEAPON }; - params[2] = VMValue(&stp); retval = true; // assume success wantret = NULL; // assume no return value wanted numret = 0; @@ -167,10 +167,33 @@ bool AStateProvider::CallStateChain (AActor *actor, FState *state) wantret = &ret[1]; numret = 1; } + + try { state->CheckCallerType(actor, this); - VMCallAction(state->ActionFunc, params, state->ActionFunc->ImplicitArgs, wantret, numret); + + if (state->ActionFunc->DefaultArgs.Size() > 0) + { + auto index = actionParams.Append(state->ActionFunc->DefaultArgs); + if (state->ActionFunc->ImplicitArgs >= 1) + { + actionParams[index] = actor; + } + if (state->ActionFunc->ImplicitArgs == 3) + { + actionParams[index + 1] = this; + actionParams[index + 2] = VMValue(&stp); + } + + VMCallAction(state->ActionFunc, &actionParams[index], state->ActionFunc->DefaultArgs.Size(), wantret, numret); + actionParams.Clamp(index); + } + else + { + VMValue params[3] = { actor, this, VMValue(&stp) }; + VMCallAction(state->ActionFunc, params, state->ActionFunc->ImplicitArgs, wantret, numret); + } } catch (CVMAbortException &err) { diff --git a/src/tarray.h b/src/tarray.h index 167f85fa99..8acb083de6 100644 --- a/src/tarray.h +++ b/src/tarray.h @@ -278,13 +278,30 @@ public: return Count++; } - void Append(const TArray &item) + unsigned Append(const TArray &item) { - unsigned start = Reserve(item.Size()); + unsigned start = Count; + + Grow(item.Size()); + for (unsigned i = 0; i < item.Size(); i++) { - Array[start + i] = item[i]; + new(&Array[start + i]) T(item[i]); } + return start; + } + + unsigned Append(TArray &&item) + { + unsigned start = Count; + + Grow(item.Size()); + + for (unsigned i = 0; i < item.Size(); i++) + { + new(&Array[start + i]) T(std::move(item[i])); + } + return start; } bool Pop ()