- Added DecoFindSingleNameState for the extremely common case of finding a state with only

one name in its label. This avoids the alloca and security cookie calls.
- Consolidated lots of copy-pasted code in thingdef_expression.cpp to install helper functions
  into FindDecorateBuiltinFunction().

SVN r3907 (scripting)
This commit is contained in:
Randy Heit 2012-10-26 04:04:06 +00:00
parent 5c6bf0aeb4
commit 1a02d16356
3 changed files with 80 additions and 76 deletions

View file

@ -557,3 +557,4 @@ xx(DecoFRandom)
xx(DecoCallLineSpecial) xx(DecoCallLineSpecial)
xx(DecoNameToClass) xx(DecoNameToClass)
xx(DecoFindMultiNameState) xx(DecoFindMultiNameState)
xx(DecoFindSingleNameState)

View file

@ -97,6 +97,29 @@ void ExpEmit::Free(VMFunctionBuilder *build)
} }
} }
//==========================================================================
//
// FindDecorateBuiltinFunction
//
// Returns the symbol for a decorate utility function. If not found, create
// it and install it in Actor.
//
//==========================================================================
static PSymbol *FindDecorateBuiltinFunction(FName funcname, VMNativeFunction::NativeCallType func)
{
PSymbol *sym = RUNTIME_CLASS(AActor)->Symbols.FindSymbol(funcname, false);
if (sym == NULL)
{
PSymbolVMFunction *symfunc = new PSymbolVMFunction(funcname);
VMNativeFunction *calldec = new VMNativeFunction(func, funcname);
symfunc->Function = calldec;
sym = symfunc;
RUNTIME_CLASS(AActor)->Symbols.AddSymbol(sym);
}
return sym;
}
//========================================================================== //==========================================================================
// //
// EvalExpression // EvalExpression
@ -2485,18 +2508,10 @@ int DecoRandom(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret,
ExpEmit FxRandom::Emit(VMFunctionBuilder *build) ExpEmit FxRandom::Emit(VMFunctionBuilder *build)
{ {
// Find the DecoRandom function. If not found, create it and install it // Call DecoRandom to generate a random number.
// in Actor.
VMFunction *callfunc; VMFunction *callfunc;
PSymbol *sym = RUNTIME_CLASS(AActor)->Symbols.FindSymbol(NAME_DecoRandom, false); PSymbol *sym = FindDecorateBuiltinFunction(NAME_DecoRandom, DecoRandom);
if (sym == NULL)
{
PSymbolVMFunction *symfunc = new PSymbolVMFunction(NAME_DecoRandom);
VMNativeFunction *calldec = new VMNativeFunction(DecoRandom, NAME_DecoRandom);
symfunc->Function = calldec;
sym = symfunc;
RUNTIME_CLASS(AActor)->Symbols.AddSymbol(sym);
}
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
assert(((PSymbolVMFunction *)sym)->Function != NULL); assert(((PSymbolVMFunction *)sym)->Function != NULL);
callfunc = ((PSymbolVMFunction *)sym)->Function; callfunc = ((PSymbolVMFunction *)sym)->Function;
@ -2591,18 +2606,10 @@ int DecoFRandom(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret
ExpEmit FxFRandom::Emit(VMFunctionBuilder *build) ExpEmit FxFRandom::Emit(VMFunctionBuilder *build)
{ {
// Find the DecoFRandom function. If not found, create it and install it // Call the DecoFRandom function to generate a floating point random number..
// in Actor.
VMFunction *callfunc; VMFunction *callfunc;
PSymbol *sym = RUNTIME_CLASS(AActor)->Symbols.FindSymbol(NAME_DecoFRandom, false); PSymbol *sym = FindDecorateBuiltinFunction(NAME_DecoFRandom, DecoFRandom);
if (sym == NULL)
{
PSymbolVMFunction *symfunc = new PSymbolVMFunction(NAME_DecoFRandom);
VMNativeFunction *calldec = new VMNativeFunction(DecoFRandom, NAME_DecoFRandom);
symfunc->Function = calldec;
sym = symfunc;
RUNTIME_CLASS(AActor)->Symbols.AddSymbol(sym);
}
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
assert(((PSymbolVMFunction *)sym)->Function != NULL); assert(((PSymbolVMFunction *)sym)->Function != NULL);
callfunc = ((PSymbolVMFunction *)sym)->Function; callfunc = ((PSymbolVMFunction *)sym)->Function;
@ -2681,18 +2688,10 @@ ExpVal FxRandom2::EvalExpression (AActor *self)
ExpEmit FxRandom2::Emit(VMFunctionBuilder *build) ExpEmit FxRandom2::Emit(VMFunctionBuilder *build)
{ {
// Find the DecoRandom function. If not found, create it and install it // Call the DecoRandom function to generate the random number.
// in Actor.
VMFunction *callfunc; VMFunction *callfunc;
PSymbol *sym = RUNTIME_CLASS(AActor)->Symbols.FindSymbol(NAME_DecoRandom, false); PSymbol *sym = FindDecorateBuiltinFunction(NAME_DecoRandom, DecoRandom);
if (sym == NULL)
{
PSymbolVMFunction *symfunc = new PSymbolVMFunction(NAME_DecoRandom);
VMNativeFunction *calldec = new VMNativeFunction(DecoRandom, NAME_DecoRandom);
symfunc->Function = calldec;
sym = symfunc;
RUNTIME_CLASS(AActor)->Symbols.AddSymbol(sym);
}
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
assert(((PSymbolVMFunction *)sym)->Function != NULL); assert(((PSymbolVMFunction *)sym)->Function != NULL);
callfunc = ((PSymbolVMFunction *)sym)->Function; callfunc = ((PSymbolVMFunction *)sym)->Function;
@ -3537,18 +3536,10 @@ ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build)
} }
} }
} }
// Find the DecoCallLineSpecial function. If not found, create it and install it // Call the DecoCallLineSpecial function to perform the desired special.
// in Actor.
VMFunction *callfunc; VMFunction *callfunc;
PSymbol *sym = RUNTIME_CLASS(AActor)->Symbols.FindSymbol(NAME_DecoCallLineSpecial, false); PSymbol *sym = FindDecorateBuiltinFunction(NAME_DecoCallLineSpecial, DecoCallLineSpecial);
if (sym == NULL)
{
PSymbolVMFunction *symfunc = new PSymbolVMFunction(NAME_DecoCallLineSpecial);
VMNativeFunction *calldec = new VMNativeFunction(DecoCallLineSpecial, NAME_DecoCallLineSpecial);
symfunc->Function = calldec;
sym = symfunc;
RUNTIME_CLASS(AActor)->Symbols.AddSymbol(sym);
}
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
assert(((PSymbolVMFunction *)sym)->Function != NULL); assert(((PSymbolVMFunction *)sym)->Function != NULL);
callfunc = ((PSymbolVMFunction *)sym)->Function; callfunc = ((PSymbolVMFunction *)sym)->Function;
@ -3802,18 +3793,10 @@ ExpEmit FxClassTypeCast::Emit(VMFunctionBuilder *build)
build->Emit(OP_PARAM, 0, clsname.RegType, clsname.RegNum); build->Emit(OP_PARAM, 0, clsname.RegType, clsname.RegNum);
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(const_cast<PClass *>(desttype), ATAG_OBJECT)); build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(const_cast<PClass *>(desttype), ATAG_OBJECT));
// Find the DecoNameToClass function. If not found, create it and install it // Call the DecoNameToClass function to convert from 'name' to class.
// in Actor.
VMFunction *callfunc; VMFunction *callfunc;
PSymbol *sym = RUNTIME_CLASS(AActor)->Symbols.FindSymbol(NAME_DecoNameToClass, false); PSymbol *sym = FindDecorateBuiltinFunction(NAME_DecoNameToClass, DecoNameToClass);
if (sym == NULL)
{
PSymbolVMFunction *symfunc = new PSymbolVMFunction(NAME_DecoNameToClass);
VMNativeFunction *calldec = new VMNativeFunction(DecoNameToClass, NAME_DecoNameToClass);
symfunc->Function = calldec;
sym = symfunc;
RUNTIME_CLASS(AActor)->Symbols.AddSymbol(sym);
}
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
assert(((PSymbolVMFunction *)sym)->Function != NULL); assert(((PSymbolVMFunction *)sym)->Function != NULL);
callfunc = ((PSymbolVMFunction *)sym)->Function; callfunc = ((PSymbolVMFunction *)sym)->Function;
@ -3964,18 +3947,8 @@ ExpVal FxMultiNameState::EvalExpression (AActor *self)
return ret; return ret;
} }
int DecoFindMultiNameState(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret) static int DoFindState(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, FName *names, int numnames)
{ {
assert(numparam > 1);
assert(numret == 1);
assert(ret->RegType == REGT_POINTER);
FName *names = (FName *)alloca((numparam - 1) * sizeof(FName));
for (int i = 1; i < numparam; ++i)
{
PARAM_NAME_AT(i, zaname);
names[i - 1] = zaname;
}
PARAM_OBJECT_AT(0, self, AActor); PARAM_OBJECT_AT(0, self, AActor);
FState *state = self->GetClass()->FindState(numparam - 1, names); FState *state = self->GetClass()->FindState(numparam - 1, names);
if (state == NULL) if (state == NULL)
@ -3991,6 +3964,34 @@ int DecoFindMultiNameState(VMFrameStack *stack, VMValue *param, int numparam, VM
} }
ret->SetPointer(state, ATAG_STATE); ret->SetPointer(state, ATAG_STATE);
return 1; return 1;
}
// Find a state with any number of dots in its name.
int DecoFindMultiNameState(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret)
{
assert(numparam > 1);
assert(numret == 1);
assert(ret->RegType == REGT_POINTER);
FName *names = (FName *)alloca((numparam - 1) * sizeof(FName));
for (int i = 1; i < numparam; ++i)
{
PARAM_NAME_AT(i, zaname);
names[i - 1] = zaname;
}
return DoFindState(stack, param, numparam, ret, names, numparam - 1);
}
// Find a state without any dots in its name.
int DecoFindSingleNameState(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret)
{
assert(numparam == 2);
assert(numret == 1);
assert(ret->RegType == REGT_POINTER);
PARAM_NAME_AT(1, zaname);
return DoFindState(stack, param, numparam, ret, &zaname, 1);
} }
ExpEmit FxMultiNameState::Emit(VMFunctionBuilder *build) ExpEmit FxMultiNameState::Emit(VMFunctionBuilder *build)
@ -4002,18 +4003,20 @@ ExpEmit FxMultiNameState::Emit(VMFunctionBuilder *build)
EmitConstantInt(build, names[i]); EmitConstantInt(build, names[i]);
} }
// Find the DecoFindMultiNameState function. If not found, create it and install it // For one name, use the DecoFindSingleNameState function. For more than
// in Actor. // one name, use the DecoFindMultiNameState function.
VMFunction *callfunc; VMFunction *callfunc;
PSymbol *sym = RUNTIME_CLASS(AActor)->Symbols.FindSymbol(NAME_DecoFindMultiNameState, false); PSymbol *sym;
if (sym == NULL)
if (names.Size() == 1)
{ {
PSymbolVMFunction *symfunc = new PSymbolVMFunction(NAME_DecoFindMultiNameState); sym = FindDecorateBuiltinFunction(NAME_DecoFindSingleNameState, DecoFindSingleNameState);
VMNativeFunction *calldec = new VMNativeFunction(DecoFindMultiNameState, NAME_DecoFindMultiNameState);
symfunc->Function = calldec;
sym = symfunc;
RUNTIME_CLASS(AActor)->Symbols.AddSymbol(sym);
} }
else
{
sym = FindDecorateBuiltinFunction(NAME_DecoFindMultiNameState, DecoFindMultiNameState);
}
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
assert(((PSymbolVMFunction *)sym)->Function != NULL); assert(((PSymbolVMFunction *)sym)->Function != NULL);
callfunc = ((PSymbolVMFunction *)sym)->Function; callfunc = ((PSymbolVMFunction *)sym)->Function;

View file

@ -131,8 +131,8 @@ void VMSelectEngine(EVMEngine engine)
#ifdef NDEBUG #ifdef NDEBUG
VMExec = VMExec_Unchecked::Exec; VMExec = VMExec_Unchecked::Exec;
#else #else
VMExec = VMExec_Checked::Exec;
#endif #endif
VMExec = VMExec_Checked::Exec;
break; break;
case VMEngine_Unchecked: case VMEngine_Unchecked:
VMExec = VMExec_Unchecked::Exec; VMExec = VMExec_Unchecked::Exec;