Browse Source

Optimize variable-to-variable assignment

James Urquhart 13 years ago
parent
commit
e99eadd61f

+ 2 - 1
Engine/source/console/ast.h

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

+ 45 - 6
Engine/source/console/astNodes.cpp

@@ -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;
    }

+ 40 - 0
Engine/source/console/compiledEval.cpp

@@ -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();

+ 6 - 2
Engine/source/console/compiler.h

@@ -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,

+ 3 - 0
Engine/source/console/consoleInternal.h

@@ -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();