瀏覽代碼

Improvements based on experience from implementing Python runtime

Lukas Aldershaab 2 年之前
父節點
當前提交
83ea6cd0df

+ 12 - 0
Engine/source/console/console.h

@@ -365,6 +365,18 @@ public:
       return type >= ConsoleValueType::cvConsoleValueType;
    }
 
+   TORQUE_FORCEINLINE ConsoleValueConsoleType* getConsoleType() const
+   {
+      if(type >= ConsoleValueType::cvConsoleValueType)
+      {
+         return ct;
+      }
+      else
+      {
+         return NULL;
+      }
+   }
+
    TORQUE_FORCEINLINE void setFastFloat(F64 flt)
    {
       type = ConsoleValueType::cvFloat;

+ 8 - 83
Engine/source/console/consoleInternal.cpp

@@ -181,13 +181,13 @@ void Dictionary::exportVariables(const char *varString, const char *fileName, bo
 
    for (s = sortList.begin(); s != sortList.end(); s++)
    {
-      switch ((*s)->type)
+      switch ((*s)->value.getType())
       {
-         case Entry::TypeInternalInt:
-            dSprintf(buffer, sizeof(buffer), "%s = %d;%s", (*s)->name, (*s)->ival, cat);
+         case ConsoleValueType::cvInteger:
+            dSprintf(buffer, sizeof(buffer), "%s = %d;%s", (*s)->name, (*s)->getIntValue(), cat);
             break;
-         case Entry::TypeInternalFloat:
-            dSprintf(buffer, sizeof(buffer), "%s = %g;%s", (*s)->name, (*s)->fval, cat);
+         case ConsoleValueType::cvFloat:
+            dSprintf(buffer, sizeof(buffer), "%s = %g;%s", (*s)->name, (*s)->getFloatValue(), cat);
             break;
          default:
             expandEscape(expandBuffer, (*s)->getStringValue());
@@ -241,7 +241,7 @@ void Dictionary::exportVariables(const char *varString, Vector<String> *names, V
 
       if (values)
       {
-         switch ((*s)->type)
+         switch ((*s)->value.getType())
          {
             case ConsoleValueType::cvInteger:
             case ConsoleValueType::cvFloat:
@@ -461,19 +461,11 @@ const char *Dictionary::tabComplete(const char *prevText, S32 baseLen, bool fFor
 Dictionary::Entry::Entry(StringTableEntry in_name)
 {
    name = in_name;
-   type = TypeInternalString;
    notify = NULL;
    nextEntry = NULL;
    mUsage = NULL;
    mIsConstant = false;
    mNext = NULL;
-
-   ival = 0;
-   fval = 0;
-   sval = NULL;
-   bufferLen = 0;
-   dataPtr = NULL;
-   enumTable = NULL;
 }
 
 Dictionary::Entry::~Entry()
@@ -484,73 +476,11 @@ Dictionary::Entry::~Entry()
 void Dictionary::Entry::reset()
 {
    name = NULL;
-   if (type <= TypeInternalString && sval != NULL)
-      dFree(sval);
+   value.reset();
    if (notify)
       delete notify;
 }
 
-void Dictionary::Entry::setStringValue(const char* value)
-{
-   if (mIsConstant)
-   {
-      Con::errorf("Cannot assign value to constant '%s'.", name);
-      return;
-   }
-
-   if (type <= TypeInternalString)
-   {
-      // Let's not remove empty-string-valued global vars from the dict.
-      // If we remove them, then they won't be exported, and sometimes
-      // it could be necessary to export such a global.  There are very
-      // few empty-string global vars so there's no performance-related
-      // need to remove them from the dict.
-      /*
-       if(!value[0] && name[0] == '$')
-       {
-       gEvalState.globalVars.remove(this);
-       return;
-       }
-       */
-
-      U32 stringLen = dStrlen(value);
-
-      // If it's longer than 256 bytes, it's certainly not a number.
-      //
-      // (This decision may come back to haunt you. Shame on you if it
-      // does.)
-      if (stringLen < 256)
-      {
-         fval = dAtof(value);
-         ival = dAtoi(value);
-      }
-      else
-      {
-         fval = 0.f;
-         ival = 0;
-      }
-
-      type = TypeInternalString;
-
-      // may as well pad to the next cache line
-      U32 newLen = ((stringLen + 1) + 15) & ~15;
-
-      if (sval == NULL)
-         sval = (char*)dMalloc(newLen);
-      else if (newLen > bufferLen)
-         sval = (char*)dRealloc(sval, newLen);
-
-      bufferLen = newLen;
-      dStrcpy(sval, value, newLen);
-   }
-   else
-      Con::setData(type, dataPtr, 0, 1, &value, enumTable);
-
-   // Fire off the notification if we have one.
-   if (notify)
-      notify->trigger();
-}
-
 const char *Dictionary::getVariable(StringTableEntry name, bool *entValid)
 {
    Entry *ent = lookup(name);
@@ -626,17 +556,12 @@ Dictionary::Entry* Dictionary::addVariable(const char *name,
 
    Entry *ent = add(StringTable->insert(name));
 
-   if (ent->type <= Entry::TypeInternalString && ent->sval != NULL)
-      dFree(ent->sval);
-
    ent->mUsage = usage;
-   ent->type = type;
-   ent->dataPtr = dataPtr;
 
    // Fetch enum table, if any.
    ConsoleBaseType* conType = ConsoleBaseType::getType(type);
    AssertFatal(conType, "Dictionary::addVariable - invalid console type");
-   ent->enumTable = conType->getEnumTable();
+   ent->value.setConsoleData(type, dataPtr, conType->getEnumTable());
 
    return ent;
 }

+ 39 - 89
Engine/source/console/consoleInternal.h

@@ -286,16 +286,8 @@ public:
    {
       friend class Dictionary;
 
-      enum
-      {
-         TypeInternalInt = -3,
-         TypeInternalFloat = -2,
-         TypeInternalString = -1,
-      };
-
       StringTableEntry name;
       Entry *nextEntry;
-      S32 type;
 
       typedef Signal<void()> NotifySignal;
 
@@ -309,58 +301,17 @@ public:
       /// Whether this is a constant that cannot be assigned to.
       bool mIsConstant;
 
-   protected:
-
-      // NOTE: This is protected to ensure no one outside
-      // of this structure is messing with it.
-
-#pragma warning( push )
-#pragma warning( disable : 4201 ) // warning C4201: nonstandard extension used : nameless struct/union
-
-      // An variable is either a real dynamic type or
-      // its one exposed from C++ using a data pointer.
-      //
-      // We use this nameless union and struct setup
-      // to optimize the memory usage.
-      union
-      {
-         struct
-         {
-            char* sval;
-            U32 ival;  // doubles as strlen when type is TypeInternalString
-            F32 fval;
-            U32 bufferLen;
-         };
-
-         struct
-         {
-            /// The real data pointer.
-            void* dataPtr;
-
-            /// The enum lookup table for enumerated types.
-            const EnumTable* enumTable;
-         };
-      };
-
-#pragma warning( pop ) // C4201
+      ConsoleValue value;
 
    public:
 
       Entry() {
          name = NULL;
-         type = TypeInternalString;
          notify = NULL;
          nextEntry = NULL;
          mUsage = NULL;
          mIsConstant = false;
          mNext = NULL;
-
-         ival = 0;
-         fval = 0;
-         sval = NULL;
-         bufferLen = 0;
-         dataPtr = NULL;
-         enumTable = NULL;
       }
 
       Entry(StringTableEntry name);
@@ -370,32 +321,21 @@ public:
 
       void reset();
 
+      inline ConsoleValue getValue() { return std::move(value); }
+
       inline U32 getIntValue()
       {
-         if (type <= TypeInternalString)
-            return ival;
-         else
-            return dAtoi(Con::getData(type, dataPtr, 0, enumTable));
+         return value.getInt();
       }
 
       inline F32 getFloatValue()
       {
-         if (type <= TypeInternalString)
-            return fval;
-         else
-            return dAtof(Con::getData(type, dataPtr, 0, enumTable));
+         return value.getFloat();
       }
 
       inline const char *getStringValue()
       {
-         if (type == TypeInternalString)
-            return sval;
-         if (type == TypeInternalFloat)
-            return Con::getData(TypeF32, &fval, 0);
-         else if (type == TypeInternalInt)
-            return Con::getData(TypeS32, &ival, 0);
-         else
-            return Con::getData(type, dataPtr, 0, enumTable);
+         return value.getString();
       }
 
       void setIntValue(U32 val)
@@ -406,21 +346,15 @@ public:
             return;
          }
 
-         if (type <= TypeInternalString)
+         if (value.isConsoleType())
          {
-            fval = (F32)val;
-            ival = val;
-            if (sval != NULL)
-            {
-               dFree(sval);
-               sval = NULL;
-            }
-            type = TypeInternalInt;
+            const char* dptr = Con::getData(TypeS32, &val, 0);
+            ConsoleValueConsoleType* cvt = value.getConsoleType();
+            Con::setData(cvt->consoleType, cvt->dataPtr, 0, 1, &dptr, cvt->enumTable);
          }
          else
          {
-            const char* dptr = Con::getData(TypeS32, &val, 0);
-            Con::setData(type, dataPtr, 0, 1, &dptr, enumTable);
+            value.setInt(val);
          }
 
          // Fire off the notification if we have one.
@@ -436,21 +370,15 @@ public:
             return;
          }
 
-         if (type <= TypeInternalString)
+         if (value.isConsoleType())
          {
-            fval = val;
-            ival = static_cast<U32>(val);
-            if (sval != NULL)
-            {
-               dFree(sval);
-               sval = NULL;
-            }
-            type = TypeInternalFloat;
+            const char* dptr = Con::getData(TypeF32, &val, 0);
+            ConsoleValueConsoleType* cvt = value.getConsoleType();
+            Con::setData(cvt->consoleType, cvt->dataPtr, 0, 1, &dptr, cvt->enumTable);
          }
          else
          {
-            const char* dptr = Con::getData(TypeF32, &val, 0);
-            Con::setData(type, dataPtr, 0, 1, &dptr, enumTable);
+            value.setFloat(val);
          }
 
          // Fire off the notification if we have one.
@@ -458,7 +386,29 @@ public:
             notify->trigger();
       }
 
-      void setStringValue(const char* value);
+
+      void setStringValue(const char* val)
+      {
+         if (mIsConstant)
+         {
+            Con::errorf("Cannot assign value to constant '%s'.", name);
+            return;
+         }
+
+         if (value.isConsoleType())
+         {
+            ConsoleValueConsoleType* cvt = value.getConsoleType();
+            Con::setData(cvt->consoleType, cvt->dataPtr, 0, 1, &val, cvt->enumTable);
+         }
+         else
+         {
+            value.setString(val);
+         }
+
+         // Fire off the notification if we have one.
+         if (notify)
+            notify->trigger();
+      }
    };
 
    struct HashTableData

+ 5 - 5
Engine/source/console/engineDoc.cpp

@@ -112,10 +112,10 @@ static void dumpVariable(  Stream& stream,
                            const char* inClass = NULL )
 {
    // Skip variables defined in script.
-   
-   if( entry->type <= Dictionary::Entry::TypeInternalString )
+
+   if( entry->value.getType() <= ConsoleValueType::cvString )
       return;
-         
+
    // Skip internals... don't export them.
    if (  entry->mUsage &&
          ( dStrstr( entry->mUsage, "@hide" ) || dStrstr( entry->mUsage, "@internal" ) ) )
@@ -145,10 +145,10 @@ static void dumpVariable(  Stream& stream,
       if( nameComponents.size() > 1 && Con::lookupNamespace( nameComponents.first().c_str() + 1 )->mClassRep )
          return;
    }
-            
+
    // Skip variables for which we can't decipher their type.
 
-   ConsoleBaseType* type = ConsoleBaseType::getType( entry->type );
+   ConsoleBaseType* type = ConsoleBaseType::getType( entry->value.getConsoleType()->consoleType );
    if( !type )
    {
       Con::errorf( "Can't find type for variable '%s'", entry->name );

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

@@ -4,6 +4,7 @@
 #include "runtime.h"
 #include "core/stream/stream.h"
 #include "module.h"
+#include "core/util/tDictionary.h"
 
 namespace Con
 {
@@ -24,15 +25,10 @@ namespace Con
 
    Module* getCurrentModule();
 
-   inline Vector<Runtime*> gRuntimes(32);
+   inline HashMap<S32, Runtime*> gRuntimes;
    inline Runtime* getRuntime(S32 pRuntimeId = 0) { return gRuntimes[pRuntimeId]; }
    inline void registerRuntime(S32 pRuntimeId, Runtime* pRuntime)
    {
-      if (gRuntimes.size() == 0)
-      {
-         gRuntimes.setSize(pRuntimeId + 1);
-         gRuntimes.fill(NULL);
-      }
       AssertFatal(gRuntimes[pRuntimeId] == NULL, "A runtime with that ID already exists");
       gRuntimes[pRuntimeId] = pRuntime;
    }

+ 1 - 5
Engine/source/console/torquescript/runtime.cpp

@@ -95,16 +95,12 @@ namespace TorqueScript
    //------------------------------------------------------------------------------
    Con::EvalResult TorqueScriptRuntime::evaluatef(const char* string, ...)
    {
-      ConsoleStackFrameSaver stackSaver;
-      stackSaver.save();
-
       char buffer[4096];
       va_list args;
       va_start(args, string);
       dVsprintf(buffer, sizeof(buffer), string, args);
       va_end(args);
-      CodeBlock* newCodeBlock = new CodeBlock();
-      return newCodeBlock->compileExec(NULL, buffer, false, 0);
+      return evaluate(buffer);
    }
 
    bool TorqueScriptRuntime::executeFile(const char* fileName, bool noCalls, bool journalScript)