diff --git a/src/memarena.cpp b/src/memarena.cpp index b15fb12ea..e6e9edd6e 100644 --- a/src/memarena.cpp +++ b/src/memarena.cpp @@ -43,8 +43,6 @@ #include "c_dispatch.h" #include "zstring.h" -#define BLOCK_SIZE (10*1024) - struct FMemArena::Block { Block *NextBlock; @@ -74,10 +72,11 @@ static inline void *RoundPointer(void *ptr) // //========================================================================== -FMemArena::FMemArena() +FMemArena::FMemArena(int bs) { TopBlock = NULL; FreeBlocks = NULL; + BlockSize = bs; } //========================================================================== @@ -191,14 +190,14 @@ FMemArena::Block *FMemArena::AddBlock(size_t size) if (mem == NULL) { // Allocate a new block - if (size < BLOCK_SIZE) + if (size < BlockSize) { - size = BLOCK_SIZE; + size = BlockSize; } else { // Stick some free space at the end so we can use this block for // other things. - size += BLOCK_SIZE/2; + size += BlockSize/2; } mem = (Block *)M_Malloc(size); mem->Limit = (BYTE *)mem + size; diff --git a/src/memarena.h b/src/memarena.h index 73dbb5932..cc0c8f148 100644 --- a/src/memarena.h +++ b/src/memarena.h @@ -40,7 +40,7 @@ class FMemArena { public: - FMemArena(); + FMemArena(int blocksize = 10*1024); ~FMemArena(); void *Alloc(size_t size); @@ -55,6 +55,7 @@ protected: Block *TopBlock; Block *FreeBlocks; + int BlockSize; }; // An arena specializing in storage of FStrings. It knows how to free them, diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index af92bf72f..316ae4246 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -57,6 +57,7 @@ #include "math/cmath.h" extern FRandom pr_exrandom; +FMemArena FxAlloc(65536); struct FLOP { @@ -483,7 +484,9 @@ FxVectorValue::FxVectorValue(FxExpression *x, FxExpression *y, FxExpression *z, FxVectorValue::~FxVectorValue() { for (auto &a : xyz) + { SAFE_DELETE(a); + } } FxExpression *FxVectorValue::Resolve(FCompileContext&ctx) @@ -3721,6 +3724,8 @@ ExpEmit FxBinaryLogical::Emit(VMFunctionBuilder *build) build->Emit(OP_JMP, 1); auto ctarget = build->Emit(OP_LI, to.RegNum, (Operator == TK_AndAnd) ? 0 : 1); for (auto addr : patchspots) build->Backpatch(addr, ctarget); + list.Clear(); + list.ShrinkToFit(); return to; } @@ -4362,6 +4367,7 @@ FxMinMax::FxMinMax(TArray &expr, FName type, const FScriptPositio for (unsigned i = 0; i < expr.Size(); ++i) { choices[i] = expr[i]; + expr[i] = nullptr; } } @@ -4713,10 +4719,12 @@ FxRandomPick::FxRandomPick(FRandom *r, TArray &expr, bool floaty, if (floaty) { choices[index] = new FxFloatCast(expr[index]); + expr[index] = nullptr; } else { choices[index] = new FxIntCast(expr[index], nowarn); + expr[index] = nullptr; } } @@ -5218,6 +5226,11 @@ FxMemberIdentifier::FxMemberIdentifier(FxExpression *left, FName name, const FSc ExprType = EFX_MemberIdentifier; } +FxMemberIdentifier::~FxMemberIdentifier() +{ + SAFE_DELETE(Object); +} + //========================================================================== // // @@ -5277,6 +5290,7 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx) return nullptr; } auto x = isclass? new FxClassMember(Object, vsym, ScriptPosition) : new FxStructMember(Object, vsym, ScriptPosition); + Object = nullptr; delete this; return x->Resolve(ctx); } @@ -5313,6 +5327,7 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx) ScriptPosition.Message(MSG_WARNING, "Accessing deprecated member variable %s", vsym->SymbolName.GetChars()); } auto x = new FxStructMember(Object, vsym, ScriptPosition); + Object = nullptr; delete this; return x->Resolve(ctx); } @@ -5942,12 +5957,12 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build) // //========================================================================== -FxFunctionCall::FxFunctionCall(FName methodname, FName rngname, FArgumentList *args, const FScriptPosition &pos) +FxFunctionCall::FxFunctionCall(FName methodname, FName rngname, FArgumentList &args, const FScriptPosition &pos) : FxExpression(EFX_FunctionCall, pos) { MethodName = methodname; RNG = &pr_exrandom; - ArgList = args; + ArgList = std::move(args); if (rngname != NAME_None) { switch (MethodName) @@ -5976,7 +5991,6 @@ FxFunctionCall::FxFunctionCall(FName methodname, FName rngname, FArgumentList *a FxFunctionCall::~FxFunctionCall() { - SAFE_DELETE(ArgList); } //========================================================================== @@ -5985,9 +5999,9 @@ FxFunctionCall::~FxFunctionCall() // //========================================================================== -static bool CheckArgSize(FName fname, FArgumentList *args, int min, int max, FScriptPosition &sc) +static bool CheckArgSize(FName fname, FArgumentList &args, int min, int max, FScriptPosition &sc) { - int s = args ? args->Size() : 0; + int s = args.Size(); if (s < min) { sc.Message(MSG_ERROR, "Insufficient arguments in call to %s, expected %d, got %d", fname.GetChars(), min, s); @@ -6030,7 +6044,6 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) } auto self = !(afd->Variants[0].Flags & VARF_Static)? new FxSelf(ScriptPosition) : nullptr; auto x = new FxVMFunctionCall(self, afd, ArgList, ScriptPosition, false); - ArgList = nullptr; delete this; return x->Resolve(ctx); } @@ -6040,7 +6053,6 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) if (MethodName == FxFlops[i].Name) { FxExpression *x = new FxFlopFunctionCall(i, ArgList, ScriptPosition); - ArgList = nullptr; delete this; return x->Resolve(ctx); } @@ -6059,7 +6071,7 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) } if (special != 0 && min >= 0) { - int paramcount = ArgList? ArgList->Size() : 0; + int paramcount = ArgList.Size(); if (paramcount < min) { ScriptPosition.Message(MSG_ERROR, "Not enough parameters for '%s' (expected %d, got %d)", @@ -6076,7 +6088,6 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) } FxExpression *self = (ctx.Function && ctx.Function->Variants[0].Flags & VARF_Method) ? new FxSelf(ScriptPosition) : nullptr; FxExpression *x = new FxActionSpecialCall(self, special, ArgList, ScriptPosition); - ArgList = nullptr; delete this; return x->Resolve(ctx); } @@ -6086,8 +6097,8 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) { if (CheckArgSize(MethodName, ArgList, 1, 1, ScriptPosition)) { - FxExpression *x = new FxDynamicCast(cls, (*ArgList)[0]); - (*ArgList)[0] = nullptr; + FxExpression *x = new FxDynamicCast(cls, ArgList[0]); + ArgList[0] = nullptr; delete this; return x->Resolve(ctx); } @@ -6126,29 +6137,29 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) MethodName == NAME_Color ? TypeColor : MethodName == NAME_State? TypeState :(PType*)TypeSound; - func = new FxTypeCast((*ArgList)[0], type, true, true); - (*ArgList)[0] = nullptr; + func = new FxTypeCast(ArgList[0], type, true, true); + ArgList[0] = nullptr; } break; case NAME_Random: // allow calling Random without arguments to default to (0, 255) - if (ArgList->Size() == 0) + if (ArgList.Size() == 0) { func = new FxRandom(RNG, new FxConstant(0, ScriptPosition), new FxConstant(255, ScriptPosition), ScriptPosition, ctx.FromDecorate); } else if (CheckArgSize(NAME_Random, ArgList, 2, 2, ScriptPosition)) { - func = new FxRandom(RNG, (*ArgList)[0], (*ArgList)[1], ScriptPosition, ctx.FromDecorate); - (*ArgList)[0] = (*ArgList)[1] = nullptr; + func = new FxRandom(RNG, ArgList[0], ArgList[1], ScriptPosition, ctx.FromDecorate); + ArgList[0] = ArgList[1] = nullptr; } break; case NAME_FRandom: if (CheckArgSize(NAME_FRandom, ArgList, 2, 2, ScriptPosition)) { - func = new FxFRandom(RNG, (*ArgList)[0], (*ArgList)[1], ScriptPosition); - (*ArgList)[0] = (*ArgList)[1] = nullptr; + func = new FxFRandom(RNG, ArgList[0], ArgList[1], ScriptPosition); + ArgList[0] = ArgList[1] = nullptr; } break; @@ -6156,16 +6167,15 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) case NAME_FRandomPick: if (CheckArgSize(MethodName, ArgList, 1, -1, ScriptPosition)) { - func = new FxRandomPick(RNG, *ArgList, MethodName == NAME_FRandomPick, ScriptPosition, ctx.FromDecorate); - for (auto &i : *ArgList) i = nullptr; + func = new FxRandomPick(RNG, ArgList, MethodName == NAME_FRandomPick, ScriptPosition, ctx.FromDecorate); } break; case NAME_Random2: if (CheckArgSize(NAME_Random2, ArgList, 0, 1, ScriptPosition)) { - func = new FxRandom2(RNG, ArgList->Size() == 0? nullptr : (*ArgList)[0], ScriptPosition, ctx.FromDecorate); - if (ArgList->Size() > 0) (*ArgList)[0] = nullptr; + func = new FxRandom2(RNG, ArgList.Size() == 0? nullptr : ArgList[0], ScriptPosition, ctx.FromDecorate); + if (ArgList.Size() > 0) ArgList[0] = nullptr; } break; @@ -6173,8 +6183,7 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) case NAME_Max: if (CheckArgSize(MethodName, ArgList, 2, -1, ScriptPosition)) { - func = new FxMinMax(*ArgList, MethodName, ScriptPosition); - for (auto &i : *ArgList) i = nullptr; + func = new FxMinMax(ArgList, MethodName, ScriptPosition); } break; @@ -6183,20 +6192,20 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) { TArray pass; pass.Resize(2); - pass[0] = (*ArgList)[0]; - pass[1] = (*ArgList)[1]; + pass[0] = ArgList[0]; + pass[1] = ArgList[1]; pass[0] = new FxMinMax(pass, NAME_Max, ScriptPosition); - pass[1] = (*ArgList)[2]; + pass[1] = ArgList[2]; func = new FxMinMax(pass, NAME_Min, ScriptPosition); - (*ArgList)[0] = (*ArgList)[1] = (*ArgList)[2] = nullptr; + ArgList[0] = ArgList[1] = ArgList[2] = nullptr; } break; case NAME_Abs: if (CheckArgSize(MethodName, ArgList, 1, 1, ScriptPosition)) { - func = new FxAbs((*ArgList)[0]); - (*ArgList)[0] = nullptr; + func = new FxAbs(ArgList[0]); + ArgList[0] = nullptr; } break; @@ -6204,8 +6213,8 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) case NAME_VectorAngle: if (CheckArgSize(MethodName, ArgList, 2, 2, ScriptPosition)) { - func = MethodName == NAME_ATan2 ? new FxATan2((*ArgList)[0], (*ArgList)[1], ScriptPosition) : new FxATan2((*ArgList)[1], (*ArgList)[0], ScriptPosition); - (*ArgList)[0] = (*ArgList)[1] = nullptr; + func = MethodName == NAME_ATan2 ? new FxATan2(ArgList[0], ArgList[1], ScriptPosition) : new FxATan2(ArgList[1], ArgList[0], ScriptPosition); + ArgList[0] = ArgList[1] = nullptr; } break; @@ -6229,12 +6238,12 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) // //========================================================================== -FxMemberFunctionCall::FxMemberFunctionCall(FxExpression *self, FName methodname, FArgumentList *args, const FScriptPosition &pos) +FxMemberFunctionCall::FxMemberFunctionCall(FxExpression *self, FName methodname, FArgumentList &args, const FScriptPosition &pos) : FxExpression(EFX_MemberFunctionCall, pos) { Self = self; MethodName = methodname; - ArgList = args; + ArgList = std::move(args); } //========================================================================== @@ -6246,7 +6255,6 @@ FxMemberFunctionCall::FxMemberFunctionCall(FxExpression *self, FName methodname, FxMemberFunctionCall::~FxMemberFunctionCall() { SAFE_DELETE(Self); - SAFE_DELETE(ArgList); } //========================================================================== @@ -6342,7 +6350,6 @@ isresolved: // do not pass the self pointer to static functions. auto self = (afd->Variants[0].Flags & VARF_Method) ? Self : nullptr; auto x = new FxVMFunctionCall(self, afd, ArgList, ScriptPosition, staticonly); - ArgList = nullptr; if (Self == self) Self = nullptr; delete this; return x->Resolve(ctx); @@ -6358,12 +6365,12 @@ isresolved: // //========================================================================== -FxActionSpecialCall::FxActionSpecialCall(FxExpression *self, int special, FArgumentList *args, const FScriptPosition &pos) +FxActionSpecialCall::FxActionSpecialCall(FxExpression *self, int special, FArgumentList &args, const FScriptPosition &pos) : FxExpression(EFX_ActionSpecialCall, pos) { Self = self; Special = special; - ArgList = args; + ArgList = std::move(args); EmitTail = false; } @@ -6376,7 +6383,6 @@ FxActionSpecialCall::FxActionSpecialCall(FxExpression *self, int special, FArgum FxActionSpecialCall::~FxActionSpecialCall() { SAFE_DELETE(Self); - SAFE_DELETE(ArgList); } //========================================================================== @@ -6403,51 +6409,48 @@ FxExpression *FxActionSpecialCall::Resolve(FCompileContext& ctx) bool failed = false; SAFE_RESOLVE_OPT(Self, ctx); - if (ArgList != nullptr) + for (unsigned i = 0; i < ArgList.Size(); i++) { - for (unsigned i = 0; i < ArgList->Size(); i++) + ArgList[i] = ArgList[i]->Resolve(ctx); + if (ArgList[i] == nullptr) { - (*ArgList)[i] = (*ArgList)[i]->Resolve(ctx); - if ((*ArgList)[i] == nullptr) + failed = true; + } + else if (Special < 0 && i == 0) + { + if (ArgList[i]->ValueType == TypeString) { + ArgList[i] = new FxNameCast(ArgList[i]); + ArgList[i] = ArgList[i]->Resolve(ctx); + if (ArgList[i] == nullptr) + { + failed = true; + } + } + else if (ArgList[i]->ValueType != TypeName) + { + ScriptPosition.Message(MSG_ERROR, "Name expected for parameter %d", i); failed = true; } - else if (Special < 0 && i == 0) - { - if ((*ArgList)[i]->ValueType == TypeString) - { - (*ArgList)[i] = new FxNameCast((*ArgList)[i]); - (*ArgList)[i] = (*ArgList)[i]->Resolve(ctx); - if ((*ArgList)[i] == nullptr) - { - failed = true; - } - } - else if ((*ArgList)[i]->ValueType != TypeName) - { - ScriptPosition.Message(MSG_ERROR, "Name expected for parameter %d", i); - failed = true; - } - } - else if (!(*ArgList)[i]->IsInteger()) - { - if ((*ArgList)[i]->ValueType->GetRegType() == REGT_FLOAT /* lax */) - { - (*ArgList)[i] = new FxIntCast((*ArgList)[i], ctx.FromDecorate); - } - else - { - ScriptPosition.Message(MSG_ERROR, "Integer expected for parameter %d", i); - failed = true; - } - } } - if (failed) + else if (!ArgList[i]->IsInteger()) { - delete this; - return nullptr; + if (ArgList[i]->ValueType->GetRegType() == REGT_FLOAT /* lax */) + { + ArgList[i] = new FxIntCast(ArgList[i], ctx.FromDecorate); + } + else + { + ScriptPosition.Message(MSG_ERROR, "Integer expected for parameter %d", i); + failed = true; + } } } + if (failed) + { + delete this; + return nullptr; + } ValueType = TypeSInt32; return this; } @@ -6481,30 +6484,27 @@ ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build) // fixme: This really should use the Self pointer that got passed to this class instead of just using the first argument from the function. // Once static functions are possible, or specials can be called through a member access operator this won't work anymore. build->Emit(OP_PARAM, 0, REGT_POINTER, 0); // pass self - if (ArgList != nullptr) + for (; i < ArgList.Size(); ++i) { - for (; i < ArgList->Size(); ++i) + FxExpression *argex = ArgList[i]; + if (Special < 0 && i == 0) { - FxExpression *argex = (*ArgList)[i]; - if (Special < 0 && i == 0) + assert(argex->ValueType == TypeName); + assert(argex->isConstant()); + build->EmitParamInt(-static_cast(argex)->GetValue().GetName()); + } + else + { + assert(argex->ValueType->GetRegType() == REGT_INT); + if (argex->isConstant()) { - assert(argex->ValueType == TypeName); - assert(argex->isConstant()); - build->EmitParamInt(-static_cast(argex)->GetValue().GetName()); + build->EmitParamInt(static_cast(argex)->GetValue().GetInt()); } else { - assert(argex->ValueType->GetRegType() == REGT_INT); - if (argex->isConstant()) - { - build->EmitParamInt(static_cast(argex)->GetValue().GetInt()); - } - else - { - ExpEmit arg(argex->Emit(build)); - build->Emit(OP_PARAM, 0, arg.RegType, arg.RegNum); - arg.Free(build); - } + ExpEmit arg(argex->Emit(build)); + build->Emit(OP_PARAM, 0, arg.RegType, arg.RegNum); + arg.Free(build); } } } @@ -6515,6 +6515,8 @@ ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build) assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); assert(((PSymbolVMFunction *)sym)->Function != nullptr); callfunc = ((PSymbolVMFunction *)sym)->Function; + ArgList.Clear(); + ArgList.ShrinkToFit(); if (EmitTail) { @@ -6536,12 +6538,12 @@ ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build) // //========================================================================== -FxVMFunctionCall::FxVMFunctionCall(FxExpression *self, PFunction *func, FArgumentList *args, const FScriptPosition &pos, bool novirtual) +FxVMFunctionCall::FxVMFunctionCall(FxExpression *self, PFunction *func, FArgumentList &args, const FScriptPosition &pos, bool novirtual) : FxExpression(EFX_VMFunctionCall, pos) { Self = self; Function = func; - ArgList = args; + ArgList = std::move(args); EmitTail = false; NoVirtual = novirtual; } @@ -6554,7 +6556,6 @@ FxVMFunctionCall::FxVMFunctionCall(FxExpression *self, PFunction *func, FArgumen FxVMFunctionCall::~FxVMFunctionCall() { - SAFE_DELETE(ArgList); } //========================================================================== @@ -6581,7 +6582,7 @@ VMFunction *FxVMFunctionCall::GetDirectFunction() // then it can be a "direct" function. That is, the DECORATE // definition can call that function directly without wrapping // it inside VM code. - if ((ArgList ? ArgList->Size() : 0) == 0 && !(Function->Variants[0].Flags & VARF_Virtual)) + if (ArgList.Size() == 0 && !(Function->Variants[0].Flags & VARF_Virtual)) { return Function->Variants[0].Implementation; } @@ -6613,18 +6614,18 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) return nullptr; } - if (ArgList != nullptr) + if (ArgList.Size() > 0) { bool foundvarargs = false; PType * type = nullptr; - if (argtypes.Last() != nullptr && ArgList->Size() + implicit > argtypes.Size()) + if (argtypes.Last() != nullptr && ArgList.Size() + implicit > argtypes.Size()) { ScriptPosition.Message(MSG_ERROR, "Too many arguments in call to %s", Function->SymbolName.GetChars()); delete this; return nullptr; } - for (unsigned i = 0; i < ArgList->Size(); i++) + for (unsigned i = 0; i < ArgList.Size(); i++) { // Varargs must all have the same type as the last typed argument. A_Jump is the only function using it. if (!foundvarargs) @@ -6634,12 +6635,12 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) } assert(type != nullptr); - FxExpression *x = new FxTypeCast((*ArgList)[i], type, false); + FxExpression *x = new FxTypeCast(ArgList[i], type, false); x = x->Resolve(ctx); failed |= (x == nullptr); - (*ArgList)[i] = x; + ArgList[i] = x; } - int numargs = ArgList->Size() + implicit; + int numargs = ArgList.Size() + implicit; if ((unsigned)numargs < argtypes.Size() && argtypes[numargs] != nullptr) { auto flags = Function->Variants[0].ArgFlags[numargs]; @@ -6679,13 +6680,15 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) { assert(build->Registers[REGT_POINTER].GetMostUsed() >= build->NumImplicits); - int count = 0; (ArgList ? ArgList->Size() : 0); + int count = 0; if (count == 1) { ExpEmit reg; if (CheckEmitCast(build, EmitTail, reg)) { + ArgList.Clear(); + ArgList.ShrinkToFit(); return reg; } } @@ -6718,13 +6721,13 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) selfemit.Free(build); } // Emit code to pass explicit parameters - if (ArgList != nullptr) + for (unsigned i = 0; i < ArgList.Size(); ++i) { - for (unsigned i = 0; i < ArgList->Size(); ++i) - { - count += EmitParameter(build, (*ArgList)[i], ScriptPosition); - } + count += EmitParameter(build, ArgList[i], ScriptPosition); } + ArgList.Clear(); + ArgList.ShrinkToFit(); + // Get a constant register for this function VMFunction *vmfunc = Function->Variants[0].Implementation; int funcaddr = build->GetConstantAddress(vmfunc, ATAG_OBJECT); @@ -6766,7 +6769,7 @@ bool FxVMFunctionCall::CheckEmitCast(VMFunctionBuilder *build, bool returnit, Ex funcname == NAME___decorate_internal_state__ || funcname == NAME___decorate_internal_float__) { - FxExpression *arg = (*ArgList)[0]; + FxExpression *arg = ArgList[0]; if (returnit) { if (arg->isConstant() && @@ -6799,12 +6802,12 @@ bool FxVMFunctionCall::CheckEmitCast(VMFunctionBuilder *build, bool returnit, Ex // //========================================================================== -FxFlopFunctionCall::FxFlopFunctionCall(size_t index, FArgumentList *args, const FScriptPosition &pos) +FxFlopFunctionCall::FxFlopFunctionCall(size_t index, FArgumentList &args, const FScriptPosition &pos) : FxExpression(EFX_FlopFunctionCall, pos) { assert(index < countof(FxFlops) && "FLOP index out of range"); Index = (int)index; - ArgList = args; + ArgList = std::move(args); } //========================================================================== @@ -6815,44 +6818,43 @@ FxFlopFunctionCall::FxFlopFunctionCall(size_t index, FArgumentList *args, const FxFlopFunctionCall::~FxFlopFunctionCall() { - SAFE_DELETE(ArgList); } FxExpression *FxFlopFunctionCall::Resolve(FCompileContext& ctx) { CHECKRESOLVED(); - if (ArgList == nullptr || ArgList->Size() != 1) + if (ArgList.Size() != 1) { ScriptPosition.Message(MSG_ERROR, "%s only has one parameter", FName(FxFlops[Index].Name).GetChars()); delete this; return nullptr; } - (*ArgList)[0] = (*ArgList)[0]->Resolve(ctx); - if ((*ArgList)[0] == nullptr) + ArgList[0] = ArgList[0]->Resolve(ctx); + if (ArgList[0] == nullptr) { delete this; return nullptr; } - if (!(*ArgList)[0]->IsNumeric()) + if (!ArgList[0]->IsNumeric()) { ScriptPosition.Message(MSG_ERROR, "numeric value expected for parameter"); delete this; return nullptr; } - if ((*ArgList)[0]->isConstant()) + if (ArgList[0]->isConstant()) { - double v = static_cast((*ArgList)[0])->GetValue().GetFloat(); + double v = static_cast(ArgList[0])->GetValue().GetFloat(); v = FxFlops[Index].Evaluate(v); FxExpression *x = new FxConstant(v, ScriptPosition); delete this; return x; } - if ((*ArgList)[0]->ValueType->GetRegType() == REGT_INT) + if (ArgList[0]->ValueType->GetRegType() == REGT_INT) { - (*ArgList)[0] = new FxFloatCast((*ArgList)[0]); + ArgList[0] = new FxFloatCast(ArgList[0]); } ValueType = TypeFloat64; return this; @@ -6865,10 +6867,12 @@ FxExpression *FxFlopFunctionCall::Resolve(FCompileContext& ctx) ExpEmit FxFlopFunctionCall::Emit(VMFunctionBuilder *build) { - ExpEmit v = (*ArgList)[0]->Emit(build); + ExpEmit v = ArgList[0]->Emit(build); assert(!v.Konst && v.RegType == REGT_FLOAT); build->Emit(OP_FLOP, v.RegNum, v.RegNum, FxFlops[Index].Flop); + ArgList.Clear(); + ArgList.ShrinkToFit(); return v; } @@ -7081,17 +7085,16 @@ bool FxCompoundStatement::CheckLocalVariable(FName name) // //========================================================================== -FxSwitchStatement::FxSwitchStatement(FxExpression *cond, FArgumentList *content, const FScriptPosition &pos) +FxSwitchStatement::FxSwitchStatement(FxExpression *cond, FArgumentList &content, const FScriptPosition &pos) : FxExpression(EFX_SwitchStatement, pos) { Condition = new FxIntCast(cond, false); - Content = content; + Content = std::move(content); } FxSwitchStatement::~FxSwitchStatement() { SAFE_DELETE(Condition); - SAFE_DELETE(Content); } FxExpression *FxSwitchStatement::Resolve(FCompileContext &ctx) @@ -7099,7 +7102,7 @@ FxExpression *FxSwitchStatement::Resolve(FCompileContext &ctx) CHECKRESOLVED(); SAFE_RESOLVE(Condition, ctx); - if (Content == nullptr || Content->Size() == 0) + if (Content.Size() == 0) { ScriptPosition.Message(MSG_WARNING, "Empty switch statement"); if (Condition->isConstant()) @@ -7117,7 +7120,7 @@ FxExpression *FxSwitchStatement::Resolve(FCompileContext &ctx) } } - for (auto &line : *Content) + for (auto &line : Content) { // Do not resolve breaks, they need special treatment inside switch blocks. if (line->ExprType != EFX_JumpStatement || static_cast(line)->Token != TK_Break) @@ -7130,7 +7133,7 @@ FxExpression *FxSwitchStatement::Resolve(FCompileContext &ctx) if (Condition->isConstant()) { ScriptPosition.Message(MSG_WARNING, "Case expression is constant"); - auto &content = *Content; + auto &content = Content; int defaultindex = -1; int defaultbreak = -1; int caseindex = -1; @@ -7182,7 +7185,7 @@ FxExpression *FxSwitchStatement::Resolve(FCompileContext &ctx) int mincase = INT_MAX; int maxcase = INT_MIN; - for (auto line : *Content) + for (auto line : Content) { if (line->ExprType == EFX_CaseStatement) { @@ -7227,7 +7230,7 @@ ExpEmit FxSwitchStatement::Emit(VMFunctionBuilder *build) size_t DefaultAddress = build->Emit(OP_JMP, 0); TArray BreakAddresses; - for (auto line : *Content) + for (auto line : Content) { switch (line->ExprType) { @@ -7266,6 +7269,8 @@ ExpEmit FxSwitchStatement::Emit(VMFunctionBuilder *build) { build->BackpatchToHere(addr); } + Content.Clear(); + Content.ShrinkToFit(); return ExpEmit(); } @@ -7278,14 +7283,14 @@ ExpEmit FxSwitchStatement::Emit(VMFunctionBuilder *build) bool FxSwitchStatement::CheckReturn() { //A switch statement returns when it contains no breaks and ends with a return - for (auto line : *Content) + for (auto line : Content) { if (line->ExprType == EFX_JumpStatement) { return false; // Break means that the end of the statement will be reached, Continue cannot happen in the last statement of the last block. } } - return Content->Size() > 0 && Content->Last()->CheckReturn(); + return Content.Size() > 0 && Content.Last()->CheckReturn(); } //========================================================================== @@ -8414,6 +8419,8 @@ ExpEmit FxMultiNameState::Emit(VMFunctionBuilder *build) build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), names.Size() + 1, 1); build->Emit(OP_RESULT, 0, REGT_POINTER, dest.RegNum); + names.Clear(); + names.ShrinkToFit(); return dest; } @@ -8433,6 +8440,11 @@ FxLocalVariableDeclaration::FxLocalVariableDeclaration(PType *type, FName name, Init = initval == nullptr? nullptr : new FxTypeCast(initval, type, false); } +FxLocalVariableDeclaration::~FxLocalVariableDeclaration() +{ + SAFE_DELETE(Init); +} + FxExpression *FxLocalVariableDeclaration::Resolve(FCompileContext &ctx) { CHECKRESOLVED(); diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index df0ba7594..46d419051 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -56,6 +56,8 @@ class VMFunctionBuilder; class FxJumpStatement; +extern FMemArena FxAlloc; + //========================================================================== // // @@ -317,6 +319,14 @@ public: bool isresolved = false; bool NeedResult = true; // should be set to false if not needed and properly handled by all nodes for their subnodes to eliminate redundant code EFxType ExprType; + + void *operator new(size_t size) + { + return FxAlloc.Alloc(size); + } + + void operator delete(void *block) {} + void operator delete[](void *block) {} }; //========================================================================== @@ -347,6 +357,7 @@ class FxMemberIdentifier : public FxIdentifier public: FxMemberIdentifier(FxExpression *obj, FName i, const FScriptPosition &p); + ~FxMemberIdentifier(); FxExpression *Resolve(FCompileContext&); }; @@ -1264,11 +1275,11 @@ class FxFunctionCall : public FxExpression { FName MethodName; FRandom *RNG; - FArgumentList *ArgList; + FArgumentList ArgList; public: - FxFunctionCall(FName methodname, FName rngname, FArgumentList *args, const FScriptPosition &pos); + FxFunctionCall(FName methodname, FName rngname, FArgumentList &args, const FScriptPosition &pos); ~FxFunctionCall(); FxExpression *Resolve(FCompileContext&); }; @@ -1284,11 +1295,11 @@ class FxMemberFunctionCall : public FxExpression { FxExpression *Self; FName MethodName; - FArgumentList *ArgList; + FArgumentList ArgList; public: - FxMemberFunctionCall(FxExpression *self, FName methodname, FArgumentList *args, const FScriptPosition &pos); + FxMemberFunctionCall(FxExpression *self, FName methodname, FArgumentList &args, const FScriptPosition &pos); ~FxMemberFunctionCall(); FxExpression *Resolve(FCompileContext&); }; @@ -1305,11 +1316,11 @@ class FxActionSpecialCall : public FxExpression int Special; bool EmitTail; FxExpression *Self; - FArgumentList *ArgList; + FArgumentList ArgList; public: - FxActionSpecialCall(FxExpression *self, int special, FArgumentList *args, const FScriptPosition &pos); + FxActionSpecialCall(FxExpression *self, int special, FArgumentList &args, const FScriptPosition &pos); ~FxActionSpecialCall(); FxExpression *Resolve(FCompileContext&); PPrototype *ReturnProto(); @@ -1325,11 +1336,11 @@ public: class FxFlopFunctionCall : public FxExpression { int Index; - FArgumentList *ArgList; + FArgumentList ArgList; public: - FxFlopFunctionCall(size_t index, FArgumentList *args, const FScriptPosition &pos); + FxFlopFunctionCall(size_t index, FArgumentList &args, const FScriptPosition &pos); ~FxFlopFunctionCall(); FxExpression *Resolve(FCompileContext&); ExpEmit Emit(VMFunctionBuilder *build); @@ -1366,10 +1377,10 @@ class FxVMFunctionCall : public FxExpression bool NoVirtual; FxExpression *Self; PFunction *Function; - FArgumentList *ArgList; + FArgumentList ArgList; public: - FxVMFunctionCall(FxExpression *self, PFunction *func, FArgumentList *args, const FScriptPosition &pos, bool novirtual); + FxVMFunctionCall(FxExpression *self, PFunction *func, FArgumentList &args, const FScriptPosition &pos, bool novirtual); ~FxVMFunctionCall(); FxExpression *Resolve(FCompileContext&); PPrototype *ReturnProto(); @@ -1429,7 +1440,7 @@ public: class FxSwitchStatement : public FxExpression { FxExpression *Condition; - FArgumentList *Content; + FArgumentList Content; struct CaseAddr { @@ -1440,7 +1451,7 @@ class FxSwitchStatement : public FxExpression TArray CaseAddresses; public: - FxSwitchStatement(FxExpression *cond, FArgumentList *content, const FScriptPosition &pos); + FxSwitchStatement(FxExpression *cond, FArgumentList &content, const FScriptPosition &pos); ~FxSwitchStatement(); FxExpression *Resolve(FCompileContext&); ExpEmit Emit(VMFunctionBuilder *build); @@ -1714,6 +1725,7 @@ public: int RegNum = -1; FxLocalVariableDeclaration(PType *type, FName name, FxExpression *initval, int varflags, const FScriptPosition &p); + ~FxLocalVariableDeclaration(); FxExpression *Resolve(FCompileContext&); ExpEmit Emit(VMFunctionBuilder *build); void Release(VMFunctionBuilder *build); diff --git a/src/scripting/decorate/thingdef_exp.cpp b/src/scripting/decorate/thingdef_exp.cpp index c63677e0c..7e4c3b398 100644 --- a/src/scripting/decorate/thingdef_exp.cpp +++ b/src/scripting/decorate/thingdef_exp.cpp @@ -482,7 +482,6 @@ static FxExpression *ParseExpression0 (FScanner &sc, PClassActor *cls) else if (sc.CheckToken(TK_Identifier)) { FName identifier = FName(sc.String); - FArgumentList *args; PFunction *func; switch (identifier) @@ -503,18 +502,12 @@ static FxExpression *ParseExpression0 (FScanner &sc, PClassActor *cls) // There is an action function ACS_NamedExecuteWithResult which must be ignored here for this to work. if (func != nullptr && identifier != NAME_ACS_NamedExecuteWithResult) { - args = new FArgumentList; + FArgumentList args; if (sc.CheckToken('(')) { sc.UnGet(); - ParseFunctionParameters(sc, cls, *args, func, "", nullptr); + ParseFunctionParameters(sc, cls, args, func, "", nullptr); } - if (args->Size() == 0) - { - delete args; - args = nullptr; - } - return new FxVMFunctionCall(new FxSelf(sc), func, args, sc, false); } } @@ -536,26 +529,17 @@ static FxExpression *ParseExpression0 (FScanner &sc, PClassActor *cls) case NAME_VectorAngle: return ParseAtan2(sc, identifier, cls); default: - args = new FArgumentList; - try + FArgumentList args; + if (!sc.CheckToken(')')) { - if (!sc.CheckToken(')')) + do { - do - { - args->Push(ParseExpressionM (sc, cls)); - } - while (sc.CheckToken(',')); - sc.MustGetToken(')'); + args.Push(ParseExpressionM (sc, cls)); } - return new FxFunctionCall(identifier, NAME_None, args, sc); + while (sc.CheckToken(',')); + sc.MustGetToken(')'); } - catch (...) - { - delete args; - throw; - } - break; + return new FxFunctionCall(identifier, NAME_None, args, sc); } } else diff --git a/src/scripting/decorate/thingdef_states.cpp b/src/scripting/decorate/thingdef_states.cpp index d17cb5d4d..e3cb74c32 100644 --- a/src/scripting/decorate/thingdef_states.cpp +++ b/src/scripting/decorate/thingdef_states.cpp @@ -75,8 +75,8 @@ FxVMFunctionCall *DoActionSpecials(FScanner &sc, FState & state, Baggage &bag) if (special > 0 && min_args >= 0) { - FArgumentList *args = new FArgumentList; - args->Push(new FxConstant(special, sc)); + FArgumentList args; + args.Push(new FxConstant(special, sc)); i = 0; // Make this consistent with all other parameter parsing @@ -84,7 +84,7 @@ FxVMFunctionCall *DoActionSpecials(FScanner &sc, FState & state, Baggage &bag) { while (i < 5) { - args->Push(new FxIntCast(ParseExpression(sc, bag.Info), true)); + args.Push(new FxIntCast(ParseExpression(sc, bag.Info), true)); i++; if (!sc.CheckToken (',')) break; } @@ -571,13 +571,9 @@ FxVMFunctionCall *ParseAction(FScanner &sc, FState state, FString statestring, B PFunction *afd = dyn_cast(bag.Info->Symbols.FindSymbol(symname, true)); if (afd != NULL) { - FArgumentList *args = new FArgumentList; - ParseFunctionParameters(sc, bag.Info, *args, afd, statestring, &bag.statedef); - call = new FxVMFunctionCall(new FxSelf(sc), afd, args->Size() > 0 ? args : NULL, sc, false); - if (args->Size() == 0) - { - delete args; - } + FArgumentList args; + ParseFunctionParameters(sc, bag.Info, args, afd, statestring, &bag.statedef); + call = new FxVMFunctionCall(new FxSelf(sc), afd, args, sc, false); return call; } sc.ScriptError("Invalid parameter '%s'\n", sc.String); diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index e5ed249b1..acb67e2f5 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -776,4 +776,5 @@ void FFunctionBuildList::Build() } FScriptPosition::StrictErrors = false; mItems.Clear(); + FxAlloc.FreeAllBlocks(); } \ No newline at end of file diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 0d99ee5c2..7db62d6fb 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2239,7 +2239,7 @@ FxExpression *ZCCCompiler::SetupActionFunction(PClass *cls, ZCC_TreeNode *af) if (fc->Parameters == nullptr && !(afd->Variants[0].Flags & VARF_Virtual)) { // We can use this function directly without wrapping it in a caller. - return new FxVMFunctionCall(new FxSelf(*af), afd, nullptr, *af, false); + return new FxVMFunctionCall(new FxSelf(*af), afd, FArgumentList(), *af, false); } } else @@ -2563,16 +2563,17 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) // - class members // - array syntax for random() calls. // Everything else coming here is a syntax error. + FArgumentList args; switch (fcall->Function->NodeType) { case AST_ExprID: // The function name is a simple identifier. - return new FxFunctionCall(static_cast(fcall->Function)->Identifier, NAME_None, ConvertNodeList(fcall->Parameters), *ast); + return new FxFunctionCall(static_cast(fcall->Function)->Identifier, NAME_None, ConvertNodeList(args, fcall->Parameters), *ast); case AST_ExprMemberAccess: { auto ema = static_cast(fcall->Function); - return new FxMemberFunctionCall(ConvertNode(ema->Left), ema->Right, ConvertNodeList(fcall->Parameters), *ast); + return new FxMemberFunctionCall(ConvertNode(ema->Left), ema->Right, ConvertNodeList(args, fcall->Parameters), *ast); } case AST_ExprBinary: @@ -2582,7 +2583,7 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) auto binary = static_cast(fcall->Function); if (binary->Left->NodeType == AST_ExprID && binary->Right->NodeType == AST_ExprID) { - return new FxFunctionCall(static_cast(binary->Left)->Identifier, static_cast(binary->Right)->Identifier, ConvertNodeList(fcall->Parameters), *ast); + return new FxFunctionCall(static_cast(binary->Left)->Identifier, static_cast(binary->Right)->Identifier, ConvertNodeList(args, fcall->Parameters), *ast); } } // fall through if this isn't an array access node. @@ -2832,21 +2833,20 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) case AST_ReturnStmt: { auto ret = static_cast(ast); - FArgumentList *args = ConvertNodeList(ret->Values); - if (args->Size() == 0) + FArgumentList args; + ConvertNodeList(args, ret->Values); + if (args.Size() == 0) { return new FxReturnStatement(nullptr, *ast); } - else if (args->Size() == 1) + else if (args.Size() == 1) { - auto arg = (*args)[0]; - (*args)[0] = nullptr; - delete args; - return new FxReturnStatement((*args)[0], *ast); + auto arg = args[0]; + args[0] = nullptr; + return new FxReturnStatement(arg, *ast); } else { - delete args; Error(ast, "Return with multiple values not implemented yet."); return new FxReturnStatement(nullptr, *ast); } @@ -2893,7 +2893,8 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) { // The switch content is wrapped into a compound statement which needs to be unraveled here. auto cmpnd = static_cast(swtch->Content); - return new FxSwitchStatement(ConvertNode(swtch->Condition), ConvertNodeList(cmpnd->Content), *ast); + FArgumentList args; + return new FxSwitchStatement(ConvertNode(swtch->Condition), ConvertNodeList(args, cmpnd->Content), *ast); } } @@ -2922,17 +2923,16 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) } -FArgumentList *ZCCCompiler::ConvertNodeList(ZCC_TreeNode *head) +FArgumentList &ZCCCompiler::ConvertNodeList(FArgumentList &args, ZCC_TreeNode *head) { - FArgumentList *list = new FArgumentList; if (head != nullptr) { auto node = head; do { - list->Push(ConvertNode(node)); + args.Push(ConvertNode(node)); node = node->SiblingNext; } while (node != head); } - return list; + return args; } \ No newline at end of file diff --git a/src/scripting/zscript/zcc_compile.h b/src/scripting/zscript/zcc_compile.h index 2e38d68d2..2e8840a46 100644 --- a/src/scripting/zscript/zcc_compile.h +++ b/src/scripting/zscript/zcc_compile.h @@ -144,7 +144,7 @@ private: FxExpression *ConvertAST(PClass *cclass, ZCC_TreeNode *ast); FxExpression *ConvertNode(ZCC_TreeNode *node); - FArgumentList *ConvertNodeList(ZCC_TreeNode *head); + FArgumentList &ConvertNodeList(FArgumentList &, ZCC_TreeNode *head); DObject *Outer; PClass *ConvertClass; // class type to be used when resoving symbold while converting an AST