Optimize variable-to-variable assignment

This commit is contained in:
James Urquhart 2012-10-04 17:58:43 +01:00
parent 38c8e52c1d
commit e99eadd61f
5 changed files with 96 additions and 9 deletions

View file

@ -38,7 +38,8 @@ enum TypeReq
TypeReqNone,
TypeReqUInt,
TypeReqFloat,
TypeReqString
TypeReqString,
TypeReqVar
};
/// Representation of a node for the scripting language parser.

View file

@ -134,6 +134,8 @@ static U32 conversionOp(TypeReq src, TypeReq dst)
return OP_STR_TO_FLT;
case TypeReqNone:
return OP_STR_TO_NONE;
case TypeReqVar:
return OP_SAVEVAR_STR;
default:
break;
}
@ -148,6 +150,8 @@ static U32 conversionOp(TypeReq src, TypeReq dst)
return OP_FLT_TO_STR;
case TypeReqNone:
return OP_FLT_TO_NONE;
case TypeReqVar:
return OP_SAVEVAR_FLT;
default:
break;
}
@ -162,6 +166,24 @@ static U32 conversionOp(TypeReq src, TypeReq dst)
return OP_UINT_TO_STR;
case TypeReqNone:
return OP_UINT_TO_NONE;
case TypeReqVar:
return OP_SAVEVAR_UINT;
default:
break;
}
}
else if(src == TypeReqVar)
{
switch(dst)
{
case TypeReqUInt:
return OP_LOADVAR_UINT;
case TypeReqFloat:
return OP_LOADVAR_FLT;
case TypeReqString:
return OP_LOADVAR_STR;
case TypeReqNone:
return OP_COPYVAR_TO_NONE;
default:
break;
}
@ -872,6 +894,7 @@ U32 VarNode::precompile(TypeReq type)
return (arrayIndex ? arrayIndex->precompile(TypeReqString) + 6 : 3);
}
// Puts value of VarNode onto StringStack/intStack/fltStack
U32 VarNode::compile(U32 *codeStream, U32 ip, TypeReq type)
{
if(type == TypeReqNone)
@ -882,10 +905,11 @@ U32 VarNode::compile(U32 *codeStream, U32 ip, TypeReq type)
ip++;
if(arrayIndex)
{
// NOTE: in this case we have the start value loaded into STR
codeStream[ip++] = OP_ADVANCE_STR;
ip = arrayIndex->compile(codeStream, ip, TypeReqString);
codeStream[ip++] = OP_REWIND_STR;
codeStream[ip++] = OP_SETCURVAR_ARRAY;
ip = arrayIndex->compile(codeStream, ip, TypeReqString); // Add on extra bits
codeStream[ip++] = OP_REWIND_STR; // Go back to start
codeStream[ip++] = OP_SETCURVAR_ARRAY; // Set variable name
}
switch(type)
{
@ -898,8 +922,13 @@ U32 VarNode::compile(U32 *codeStream, U32 ip, TypeReq type)
case TypeReqString:
codeStream[ip++] = OP_LOADVAR_STR;
break;
case TypeReqVar:
codeStream[ip++] = OP_LOADVAR_VAR;
break;
case TypeReqNone:
break;
default:
break;
}
return ip;
}
@ -1105,8 +1134,15 @@ U32 AssignExprNode::precompile(TypeReq type)
subType = expr->getPreferredType();
if(subType == TypeReqNone)
subType = type;
if(subType == TypeReqNone)
subType = TypeReqString;
if(subType == TypeReqNone) {
// jamesu - what we need to do in this case is turn it into a VarNode reference
if (dynamic_cast<VarNode*>(expr) != NULL) {
// Sanity check passed
subType = TypeReqVar;
} else {
subType = TypeReqString;
}
}
// if it's an array expr, the formula is:
// eval expr
// (push and pop if it's TypeReqString) OP_ADVANCE_STR
@ -1139,7 +1175,7 @@ U32 AssignExprNode::precompile(TypeReq type)
U32 AssignExprNode::compile(U32 *codeStream, U32 ip, TypeReq type)
{
ip = expr->compile(codeStream, ip, subType);
ip = expr->compile(codeStream, ip, subType); // this is the value of VarNode
if(arrayIndex)
{
if(subType == TypeReqString)
@ -1172,6 +1208,9 @@ U32 AssignExprNode::compile(U32 *codeStream, U32 ip, TypeReq type)
case TypeReqFloat:
codeStream[ip++] = OP_SAVEVAR_FLT;
break;
case TypeReqVar:
codeStream[ip++] = OP_SAVEVAR_VAR;
break;
case TypeReqNone:
break;
}

View file

@ -285,6 +285,24 @@ inline void ExprEvalState::setStringVariable(const char *val)
currentVariable->setStringValue(val);
}
inline void ExprEvalState::setCopyVariable()
{
if (copyVariable) {
switch (copyVariable->value.type)
{
case ConsoleValue::TypeInternalInt:
currentVariable->setIntValue(copyVariable->getIntValue());
break;
case ConsoleValue::TypeInternalFloat:
currentVariable->setFloatValue(copyVariable->getFloatValue());
break;
default:
currentVariable->setStringValue(copyVariable->getStringValue());
break;
}
}
}
//------------------------------------------------------------
// Gets a component of an object's field value or a variable and returns it
@ -1362,6 +1380,11 @@ breakContinue:
STR.setStringValue(val);
break;
case OP_LOADVAR_VAR:
// Sets current source of OP_SAVEVAR_VAR
gEvalState.copyVariable = gEvalState.currentVariable;
break;
case OP_SAVEVAR_UINT:
gEvalState.setIntVariable(intStack[_UINT]);
break;
@ -1373,6 +1396,11 @@ breakContinue:
case OP_SAVEVAR_STR:
gEvalState.setStringVariable(STR.getStringValue());
break;
case OP_SAVEVAR_VAR:
// this basically handles %var1 = %var2
gEvalState.setCopyVariable();
break;
case OP_SETCUROBJECT:
// Save the previous object for parsing vector fields.
@ -1560,6 +1588,11 @@ breakContinue:
_UINT--;
break;
case OP_COPYVAR_TO_NONE:
// nop
gEvalState.copyVariable = NULL;
break;
case OP_LOADIMMED_UINT:
intStack[_UINT+1] = code[ip++];
_UINT++;
@ -1940,6 +1973,13 @@ breakContinue:
CSTK.pushFLT(floatStack[_FLT]);
_FLT--;
break;
case OP_PUSH_VAR:
//Con::printf("Pushing variable: %s",gEvalState.getCurrentVariable()]);
if (gEvalState.currentVariable)
CSTK.pushValue(gEvalState.currentVariable->value);
else
CSTK.pushString("");
break;
case OP_PUSH_FRAME:
STR.pushFrame();

View file

@ -90,10 +90,12 @@ namespace Compiler
OP_LOADVAR_UINT,
OP_LOADVAR_FLT,
OP_LOADVAR_STR,
OP_LOADVAR_VAR,
OP_SAVEVAR_UINT,
OP_SAVEVAR_FLT,
OP_SAVEVAR_STR,
OP_SAVEVAR_VAR,
OP_SETCUROBJECT,
OP_SETCUROBJECT_NEW,
@ -120,6 +122,7 @@ namespace Compiler
OP_UINT_TO_FLT,
OP_UINT_TO_STR,
OP_UINT_TO_NONE,
OP_COPYVAR_TO_NONE,
OP_LOADIMMED_UINT,
OP_LOADIMMED_FLT,
@ -140,8 +143,9 @@ namespace Compiler
OP_COMPARE_STR,
OP_PUSH, // String
OP_PUSH_UINT, // Integer
OP_PUSH_FLT, // Float
OP_PUSH_UINT, // Integer
OP_PUSH_FLT, // Float
OP_PUSH_VAR, // Variable
OP_PUSH_FRAME, // Frame
OP_ASSERT,

View file

@ -464,6 +464,7 @@ public:
///
SimObject *thisObject;
Dictionary::Entry *currentVariable;
Dictionary::Entry *copyVariable;
bool traceOn;
U32 mStackDepth;
@ -485,12 +486,14 @@ public:
void setCurVarName(StringTableEntry name);
void setCurVarNameCreate(StringTableEntry name);
S32 getIntVariable();
F64 getFloatVariable();
const char *getStringVariable();
void setIntVariable(S32 val);
void setFloatVariable(F64 val);
void setStringVariable(const char *str);
void setCopyVariable();
void pushFrame(StringTableEntry frameName, Namespace *ns);
void popFrame();