Преглед на файлове

start cleaning up ConsoleValueRef's

Jeff Hutchinson преди 4 години
родител
ревизия
5e81c021f5

+ 4 - 5
Engine/source/console/codeBlock.h

@@ -28,7 +28,6 @@
 
 class Stream;
 class ConsoleValue;
-class ConsoleValueRef;
 
 /// Core TorqueScript code management class.
 ///
@@ -130,7 +129,7 @@ public:
    /// with, zero being the top of the stack. If the the index is
    /// -1 a new frame is created. If the index is out of range the
    /// top stack frame is used.
-   ConsoleValueRef compileExec(StringTableEntry fileName, const char *script,
+   ConsoleValue compileExec(StringTableEntry fileName, const char *script,
       bool noCalls, S32 setFrame = -1);
 
    /// Executes the existing code in the CodeBlock. The return string is any 
@@ -148,9 +147,9 @@ public:
    /// -1 a new frame is created. If the index is out of range the
    /// top stack frame is used.
    /// @param packageName The code package name or null.
-   ConsoleValueRef exec(U32 offset, const char *fnName, Namespace *ns, U32 argc,
-      ConsoleValueRef *argv, bool noCalls, StringTableEntry packageName,
+   ConsoleValue exec(U32 offset, const char *fnName, Namespace *ns, U32 argc,
+      ConsoleValue *argv, bool noCalls, StringTableEntry packageName,
       S32 setFrame = -1);
 };
 
-#endif
+#endif

+ 100 - 70
Engine/source/console/console.cpp

@@ -41,9 +41,37 @@
 #include "platform/threads/mutex.h"
 #include "core/util/journal/journal.h"
 #include "cinterface/cinterface.h"
+#include "console/consoleValueStack.h"
 
 extern StringStack STR;
-extern ConsoleValueStack CSTK;
+extern ConsoleValueStack<4096> gCallStack;
+
+S32 ConsoleValue::sBufferOffset = 0;
+char ConsoleValue::sConversionBuffer[ConversionBufferSize];
+
+void ConsoleValue::init()
+{
+   sBufferOffset = 0;
+   dMemset(sConversionBuffer, '\0', ConversionBufferSize);
+}
+
+char* ConsoleValue::convertToBuffer() const
+{
+   sBufferOffset += StringSize;
+   if (sBufferOffset > ConversionBufferSize)
+   {
+      dMemset(sConversionBuffer, '\0', ConversionBufferSize);
+      sBufferOffset = 0;
+   }
+
+   char* offset = sConversionBuffer + sBufferOffset;
+   if (type == ConsoleValueType::cvFloat)
+      dSprintf(offset, StringSize, "%.9g", f);
+   else
+      dSprintf(offset, StringSize, "%lld", i);
+
+   return offset;
+}
 
 ConsoleDocFragment* ConsoleDocFragment::smFirst;
 ExprEvalState gEvalState;
@@ -1469,7 +1497,7 @@ bool executeFile(const char* fileName, bool noCalls, bool journalScript)
    return ret;
 }
 
-ConsoleValueRef evaluate(const char* string, bool echo, const char *fileName)
+ConsoleValue evaluate(const char* string, bool echo, const char *fileName)
 {
    ConsoleStackFrameSaver stackSaver;
    stackSaver.save();
@@ -1486,11 +1514,11 @@ ConsoleValueRef evaluate(const char* string, bool echo, const char *fileName)
       fileName = StringTable->insert(fileName);
 
    CodeBlock *newCodeBlock = new CodeBlock();
-   return newCodeBlock->compileExec(fileName, string, false, fileName ? -1 : 0);
+   return std::move(newCodeBlock->compileExec(fileName, string, false, fileName ? -1 : 0));
 }
 
 //------------------------------------------------------------------------------
-ConsoleValueRef evaluatef(const char* string, ...)
+ConsoleValue evaluatef(const char* string, ...)
 {
    ConsoleStackFrameSaver stackSaver;
    stackSaver.save();
@@ -1507,36 +1535,41 @@ ConsoleValueRef evaluatef(const char* string, ...)
 //------------------------------------------------------------------------------
 
 // Internal execute for global function which does not save the stack
-ConsoleValueRef _internalExecute(S32 argc, ConsoleValueRef argv[])
+ConsoleValue _internalExecute(S32 argc, ConsoleValue argv[])
 {
+   StringTableEntry funcName = StringTable->insert(argv[0].getString());
+
    const char** argv_str = static_cast<const char**>(malloc((argc - 1) * sizeof(char *)));
    for (int i = 0; i < argc - 1; i++)
    {
-      argv_str[i] = argv[i + 1];
+      argv_str[i] = argv[i + 1].getString();
    }
    bool result;
-   const char* methodRes = CInterface::CallFunction(NULL, argv[0], argv_str, argc - 1, &result);
+   const char* methodRes = CInterface::CallFunction(NULL, funcName, argv_str, argc - 1, &result);
    free(argv_str);
    if (result)
    {
-      return ConsoleValueRef::fromValue(CSTK.pushString(methodRes));
+      ConsoleValue ret;
+      ret.setString(methodRes, dStrlen(methodRes));
+      return std::move(ret);
    }
    
    Namespace::Entry *ent;
-   StringTableEntry funcName = StringTable->insert(argv[0]);
+   
    ent = Namespace::global()->lookup(funcName);
 
    if(!ent)
    {
-      warnf(ConsoleLogEntry::Script, "%s: Unknown command.", (const char*)argv[0]);
+      warnf(ConsoleLogEntry::Script, "%s: Unknown command.", funcName);
 
       STR.clearFunctionOffset();
-      return ConsoleValueRef();
+      return std::move(ConsoleValue());
    }
-   return ent->execute(argc, argv, &gEvalState);
+
+   return std::move(ent->execute(argc, argv, &gEvalState));
 }
 
-ConsoleValueRef execute(S32 argc, ConsoleValueRef argv[])
+ConsoleValue execute(S32 argc, ConsoleValue argv[])
 {
 #ifdef TORQUE_MULTITHREAD
    if(isMainThread())
@@ -1558,23 +1591,23 @@ ConsoleValueRef execute(S32 argc, ConsoleValueRef argv[])
 #endif
 }
 
-ConsoleValueRef execute(S32 argc, const char *argv[])
+ConsoleValue execute(S32 argc, const char *argv[])
 {
    ConsoleStackFrameSaver stackSaver;
    stackSaver.save();
-   StringStackConsoleWrapper args(argc, argv);
-   return execute(args.count(), args);
+   StringArrayToConsoleValueWrapper args(argc, argv);
+   return std::move(execute(args.count(), args));
 }
 
 //------------------------------------------------------------------------------
 
 // Internal execute for object method which does not save the stack
-ConsoleValueRef _internalExecute(SimObject *object, S32 argc, ConsoleValueRef argv[], bool thisCallOnly)
+static ConsoleValue _internalExecute(SimObject *object, S32 argc, ConsoleValue argv[], bool thisCallOnly)
 {
    if(argc < 2)
    {
       STR.clearFunctionOffset();
-      return ConsoleValueRef();
+      return std::move(ConsoleValue());
    }
 
    // [neo, 10/05/2007 - #3010]
@@ -1591,65 +1624,65 @@ ConsoleValueRef _internalExecute(SimObject *object, S32 argc, ConsoleValueRef ar
       }
    }
 
+   StringTableEntry funcName = StringTable->insert(argv[0].getString());
+
    const char** argv_str = static_cast<const char**>(malloc((argc - 2) * sizeof(char *)));
    for (int i = 0; i < argc - 2; i++)
    {
-      argv_str[i] = argv[i + 2];
+      argv_str[i] = argv[i + 2].getString();
    }
    bool result;
-   const char* methodRes = CInterface::CallMethod(object, argv[0], argv_str, argc - 2, &result);
+   const char* methodRes = CInterface::CallMethod(object, funcName, argv_str, argc - 2, &result);
 
    free(argv_str);
 
    if (result)
    {
-      return ConsoleValueRef::fromValue(CSTK.pushString(methodRes));
+      ConsoleValue val;
+      val.setString(methodRes, dStrlen(methodRes));
+      return std::move(val);
    }
 
    if(object->getNamespace())
    {
       U32 ident = object->getId();
-      ConsoleValueRef oldIdent(argv[1]);
-
-      StringTableEntry funcName = StringTable->insert(argv[0]);
+      const char* oldIdent = argv[1].getString();
+      
       Namespace::Entry *ent = object->getNamespace()->lookup(funcName);
 
       if(ent == NULL)
       {
-         //warnf(ConsoleLogEntry::Script, "%s: undefined for object '%s' - id %d", funcName, object->getName(), object->getId());
+         warnf(ConsoleLogEntry::Script, "%s: undefined for object '%s' - id %d", funcName, object->getName(), object->getId());
 
          STR.clearFunctionOffset();
-         return ConsoleValueRef();
+         return std::move(ConsoleValue());
       }
 
       // Twiddle %this argument
-      ConsoleValue func_ident;
-      func_ident.setIntValue((S32)ident);
-      argv[1] = ConsoleValueRef::fromValue(&func_ident);
+      argv[1].setInt(ident);
 
       SimObject *save = gEvalState.thisObject;
       gEvalState.thisObject = object;
-      ConsoleValueRef ret = ent->execute(argc, argv, &gEvalState);
+      ConsoleValue ret = std::move(ent->execute(argc, argv, &gEvalState));
       gEvalState.thisObject = save;
 
       // Twiddle it back
-      argv[1] = oldIdent;
+      argv[1].setString(oldIdent, dStrlen(oldIdent));
 
-      return ret;
+      return std::move(ret);
    }
 
-   warnf(ConsoleLogEntry::Script, "Con::execute - %d has no namespace: %s", object->getId(), (const char*)argv[0]);
+   warnf(ConsoleLogEntry::Script, "Con::execute - %d has no namespace: %s", object->getId(), funcName);
    STR.clearFunctionOffset();
-   return ConsoleValueRef();
+   return std::move(ConsoleValue());
 }
 
-
-ConsoleValueRef execute(SimObject *object, S32 argc, ConsoleValueRef argv[], bool thisCallOnly)
+ConsoleValue execute(SimObject *object, S32 argc, ConsoleValue argv[], bool thisCallOnly)
 {
    if(argc < 2)
    {
       STR.clearFunctionOffset();
-      return ConsoleValueRef();
+      return std::move(ConsoleValue());
    }
 
    ConsoleStackFrameSaver stackSaver;
@@ -1659,7 +1692,7 @@ ConsoleValueRef execute(SimObject *object, S32 argc, ConsoleValueRef argv[], boo
    {
       if (isMainThread())
       {
-         return _internalExecute(object, argc, argv, thisCallOnly);
+         return std::move(_internalExecute(object, argc, argv, thisCallOnly));
       }
       else
       {
@@ -1669,34 +1702,34 @@ ConsoleValueRef execute(SimObject *object, S32 argc, ConsoleValueRef argv[], boo
       }
    }
 
-   warnf(ConsoleLogEntry::Script, "Con::execute - %d has no namespace: %s", object->getId(), (const char*)argv[0]);
+   warnf(ConsoleLogEntry::Script, "Con::execute - %d has no namespace: %s", object->getId(), argv[0].getString());
    STR.clearFunctionOffset();
-   return ConsoleValueRef();
+   return std::move(ConsoleValue());
 }
 
-ConsoleValueRef execute(SimObject *object, S32 argc, const char *argv[], bool thisCallOnly)
+ConsoleValue execute(SimObject *object, S32 argc, const char *argv[], bool thisCallOnly)
 {
    ConsoleStackFrameSaver stackSaver;
    stackSaver.save();
-   StringStackConsoleWrapper args(argc, argv);
-   return execute(object, args.count(), args, thisCallOnly);
+   StringArrayToConsoleValueWrapper args(argc, argv);
+   return std::move(execute(object, args.count(), args, thisCallOnly));
 }
 
-inline ConsoleValueRef _executef(SimObject *obj, S32 checkArgc, S32 argc, ConsoleValueRef *argv)
+inline ConsoleValue _executef(SimObject *obj, S32 checkArgc, S32 argc, ConsoleValue *argv)
 {
    const U32 maxArg = 12;
-   AssertWarn(checkArgc == argc, "Incorrect arg count passed to Con::executef(SimObject*)");
+   AssertFatal(checkArgc == argc, "Incorrect arg count passed to Con::executef(SimObject*)");
    AssertFatal(argc <= maxArg - 1, "Too many args passed to Con::_executef(SimObject*). Please update the function to handle more.");
-   return execute(obj, argc, argv);
+   return std::move(execute(obj, argc, argv));
 }
 
 //------------------------------------------------------------------------------
-inline ConsoleValueRef _executef(S32 checkArgc, S32 argc, ConsoleValueRef *argv)
+inline ConsoleValue _executef(S32 checkArgc, S32 argc, ConsoleValue *argv)
 {
    const U32 maxArg = 10;
    AssertFatal(checkArgc == argc, "Incorrect arg count passed to Con::executef()");
    AssertFatal(argc <= maxArg, "Too many args passed to Con::_executef(). Please update the function to handle more.");
-   return execute(argc, argv);
+   return std::move(execute(argc, argv));
 }
 
 //------------------------------------------------------------------------------
@@ -1893,16 +1926,11 @@ StringTableEntry getModNameFromPath(const char *path)
 
 void postConsoleInput( RawData data )
 {
+   // TODO(JTH): Mem leak
    // Schedule this to happen at the next time event.
-   ConsoleValue values[2];
-   ConsoleValueRef argv[2];
-
-   values[0].init();
-   values[0].setStringValue("eval");
-   values[1].init();
-   values[1].setStringValue((const char*)data.data);
-   argv[0].value = &values[0];
-   argv[1].value = &values[1];
+   ConsoleValue* argv = new ConsoleValue[2];
+   argv[0].setString("eval", 4);
+   argv[1].setString(reinterpret_cast<const char*>(data.data), dStrlen(reinterpret_cast<const char*>(data.data)));
 
    Sim::postCurrentEvent(Sim::getRootGroup(), new SimConsoleEvent(2, argv, false));
 }
@@ -2555,27 +2583,29 @@ StringArrayToConsoleValueWrapper::~StringArrayToConsoleValueWrapper()
 
 //------------------------------------------------------------------------------
 
-ConsoleValueRef _BaseEngineConsoleCallbackHelper::_exec()
+ConsoleValue _BaseEngineConsoleCallbackHelper::_exec()
 {
-   ConsoleValueRef returnValue;
    if( mThis )
    {
       // Cannot invoke callback until object has been registered
-      if (mThis->isProperlyAdded()) {
-         returnValue = Con::_internalExecute( mThis, mArgc, mArgv, false );
-      } else {
-         STR.clearFunctionOffset();
-         returnValue = ConsoleValueRef();
+      if (mThis->isProperlyAdded())
+      {
+         ConsoleValue returnValue = std::move(Con::_internalExecute( mThis, mArgc, mArgv, false ));
+         mArgc = mInitialArgc; // reset
+         return returnValue;
       }
+
+      STR.clearFunctionOffset();
+      mArgc = mInitialArgc; // reset
+      return std::move(ConsoleValue());
    }
-   else
-      returnValue = Con::_internalExecute( mArgc, mArgv );
 
+   ConsoleValue returnValue = std::move(Con::_internalExecute( mArgc, mArgv ));
    mArgc = mInitialArgc; // reset args
-   return returnValue;
+   return std::move(returnValue);
 }
 
-ConsoleValueRef _BaseEngineConsoleCallbackHelper::_execLater(SimConsoleThreadExecEvent *evt)
+ConsoleValue _BaseEngineConsoleCallbackHelper::_execLater(SimConsoleThreadExecEvent *evt)
 {
    mArgc = mInitialArgc; // reset args
    Sim::postEvent((SimObject*)Sim::getRootGroup(), evt, Sim::getCurrentTime());
@@ -2586,7 +2616,7 @@ ConsoleValueRef _BaseEngineConsoleCallbackHelper::_execLater(SimConsoleThreadExe
 
 void ConsoleStackFrameSaver::save()
 {
-   CSTK.pushFrame();
+   gCallStack.pushFrame(0);
    STR.pushFrame();
    mSaved = true;
 }
@@ -2595,7 +2625,7 @@ void ConsoleStackFrameSaver::restore()
 {
    if (mSaved)
    {
-      CSTK.popFrame();
+      gCallStack.popFrame();
       STR.popFrame();
    }
 }

+ 212 - 150
Engine/source/console/console.h

@@ -117,188 +117,250 @@ struct ConsoleLogEntry
 typedef const char *StringTableEntry;
 extern char *typeValueEmpty;
 
-class ConsoleValue
+enum ConsoleValueType
 {
-public:
+   cvNone = -5,
+   cvInteger = -4,
+   cvFloat = -3,
+   cvString = -2,
+   cvSTEntry = -1,
+   cvConsoleValueType = 0
+};
+
+struct ConsoleValueConsoleType
+{
+   void* dataPtr;
+   EnumTable* enumTable;
+};
 
-   enum
+// TODO: replace malloc/free with custom allocator...
+class ConsoleValue
+{
+   union
    {
-      TypeInternalInt = -5,
-      TypeInternalFloat = -4,
-      TypeInternalStringStackPtr = -3,
-      TypeInternalStackString = -2,
-      TypeInternalString = -1,
+      F64   f;
+      S64   i;
+      char* s;
+      void* data;
+      ConsoleValueConsoleType* ct;
    };
 
    S32 type;
 
-public:
+   enum Constants
+   {
+      ConversionBufferSize = 1024,
+      StringSize = 16
+   };
 
-   // NOTE: This is protected to ensure no one outside
-   // of this structure is messing with it.
+   static char sConversionBuffer[ConversionBufferSize];
+   static S32 sBufferOffset;
 
-#pragma warning( push )
-#pragma warning( disable : 4201 ) // warning C4201: nonstandard extension used : nameless struct/union
+   char* convertToBuffer() const;
 
-   // 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
+   TORQUE_FORCEINLINE bool isStringType() const
    {
-      struct
-      {
-         char *sval;
-         U32 ival;  // doubles as strlen when type is TypeInternalString
-         F32 fval;
-         U32 bufferLen;
-      };
+      return type == ConsoleValueType::cvString || type == ConsoleValueType::cvSTEntry;
+   }
 
-      struct
-      {
-         /// The real data pointer.
-         void *dataPtr;
+   TORQUE_FORCEINLINE bool isNumberType() const
+   {
+      return type == ConsoleValueType::cvFloat || type == ConsoleValueType::cvInteger;
+   }
 
-         /// The enum lookup table for enumerated types.
-         const EnumTable *enumTable;
-      };
-   };
+   TORQUE_FORCEINLINE bool hasAllocatedData() const
+   {
+      return type == ConsoleValueType::cvString || type >= ConsoleValueType::cvConsoleValueType;
+   }
 
-   U32 getIntValue();
-   S32 getSignedIntValue();
-   F32 getFloatValue();
-   const char *getStringValue();
-   StringStackPtr getStringStackPtr();
-   bool getBoolValue();
-
-   void setIntValue(U32 val);
-   void setIntValue(S32 val);
-   void setFloatValue(F32 val);
-   void setStringValue(const char *value);
-   void setStackStringValue(const char *value);
-   void setStringStackPtrValue(StringStackPtr ptr);
-   void setBoolValue(bool val);
-
-   void init()
+   TORQUE_FORCEINLINE const char* getConsoleData() const
    {
-      ival = 0;
-      fval = 0;
-      sval = typeValueEmpty;
-      bufferLen = 0;
-      type = TypeInternalString;
+      return Con::getData(type, ct->dataPtr, 0, ct->enumTable);
    }
 
-   void cleanup()
+   TORQUE_FORCEINLINE void cleanupData()
    {
-      if ((type <= TypeInternalString) && (bufferLen > 0))
+      if (hasAllocatedData())
       {
-         dFree(sval);
-         bufferLen = 0;
+         dFree(data);
       }
-      sval = typeValueEmpty;
-      type = ConsoleValue::TypeInternalString;
-      ival = 0;
-      fval = 0;
    }
-   ConsoleValue() { init(); };
-   ~ConsoleValue() { cleanup(); };
-};
 
-// Proxy class for console variables
-// Can point to existing console variables,
-// or act like a free floating value.
-class ConsoleValueRef
-{
 public:
-   ConsoleValue *value;
-
-   ConsoleValueRef() : value(0) { ; }
-   ~ConsoleValueRef() { ; }
-
-   ConsoleValueRef(const ConsoleValueRef &ref);
-
-   static ConsoleValueRef fromValue(ConsoleValue *value) { ConsoleValueRef ref; ref.value = value; return ref; }
-
-   const char *getStringValue() { return value ? value->getStringValue() : ""; }
-   StringStackPtr getStringStackPtrValue() { return value ? value->getStringStackPtr() : 0; }
-
-   inline U32 getIntValue() { return value ? value->getIntValue() : 0; }
-   inline S32 getSignedIntValue() { return value ? value->getSignedIntValue() : 0; }
-   inline F32 getFloatValue() { return value ? value->getFloatValue() : 0.0f; }
-   inline bool getBoolValue() { return value ? value->getBoolValue() : false; }
-
-   inline operator const char*() { return getStringValue(); }
-   inline operator String() { return String(getStringValue()); }
-   inline operator U32() { return getIntValue(); }
-   inline operator S32() { return getSignedIntValue(); }
-   inline operator F32() { return getFloatValue(); }
-   inline operator bool() { return getBoolValue(); }
-
-   inline bool isStringStackPtr() { return value ? value->type == ConsoleValue::TypeInternalStringStackPtr : false; }
-   inline bool isString() { return value ? value->type >= ConsoleValue::TypeInternalStringStackPtr : true; }
-   inline bool isInt() { return value ? value->type == ConsoleValue::TypeInternalInt : false; }
-   inline bool isFloat() { return value ? value->type == ConsoleValue::TypeInternalFloat : false; }
-   inline S32 getType() { return value ? value->type : -1; }
-
-   // Note: operators replace value
-   ConsoleValueRef& operator=(const ConsoleValueRef &other);
-   ConsoleValueRef& operator=(const char *newValue);
-   ConsoleValueRef& operator=(U32 newValue);
-   ConsoleValueRef& operator=(S32 newValue);
-   ConsoleValueRef& operator=(F32 newValue);
-   ConsoleValueRef& operator=(F64 newValue);
-};
+   ConsoleValue()
+   {
+      type = ConsoleValueType::cvNone;
+   }
+
+   ConsoleValue(ConsoleValue&& ref)
+   {
+      cleanupData();
+      type = ref.type;
 
-// Overrides to allow ConsoleValueRefs to be directly converted to S32&F32
+      switch (ref.type)
+      {
+      TORQUE_UNLIKELY
+      case cvNone:
+         break;
+      case cvInteger:
+         i = ref.i;
+         break;
+      case cvFloat:
+         f = ref.f;
+         break;
+      case cvSTEntry:
+         TORQUE_CASE_FALLTHROUGH
+      case cvString:
+         s = ref.s;
+         break;
+      default:
+         data = ref.data;
+         break;
+      }
 
-inline S32 dAtoi(ConsoleValueRef &ref)
-{
-   return ref.getSignedIntValue();
-}
+      ref.type = cvNone;
+   }
 
-inline F32 dAtof(ConsoleValueRef &ref)
-{
-   return ref.getFloatValue();
-}
+   ConsoleValue(const ConsoleValue&) = delete;
+   ConsoleValue& operator=(const ConsoleValue&) = delete;
 
-inline bool dAtob(ConsoleValue &ref)
-{
-   return ref.getBoolValue();
-}
+   TORQUE_FORCEINLINE ~ConsoleValue()
+   {
+      cleanupData();
+   }
 
+   TORQUE_FORCEINLINE F64 getFloat() const
+   {
+      AssertFatal(type == ConsoleValueType::cvNone, "Attempted to access ConsoleValue when it has no value!");
+      if (type == ConsoleValueType::cvFloat)
+         return f;
+      if (type == ConsoleValueType::cvInteger)
+         return i;
+      if (isStringType())
+         return dAtof(s);
+      return dAtof(getConsoleData());
+   }
+
+   TORQUE_FORCEINLINE S64 getInt() const
+   {
+      AssertFatal(type == ConsoleValueType::cvNone, "Attempted to access ConsoleValue when it has no value!");
+      if (type == ConsoleValueType::cvInteger)
+         return i;
+      if (type == ConsoleValueType::cvFloat)
+         return f;
+      if (isStringType())
+         return dAtoi(s);
+      return dAtoi(getConsoleData());
+   }
+
+   TORQUE_FORCEINLINE const char* getString() const
+   {
+      AssertFatal(type == ConsoleValueType::cvNone, "Attempted to access ConsoleValue when it has no value!");
+      if (isStringType())
+         return s;
+      if (isNumberType())
+         return convertToBuffer();
+      return getConsoleData();
+   }
+
+   TORQUE_FORCEINLINE bool getBool() const
+   {
+      AssertFatal(type == ConsoleValueType::cvNone, "Attempted to access ConsoleValue when it has no value!");
+      if (type == ConsoleValueType::cvInteger)
+         return (bool)i;
+      if (type == ConsoleValueType::cvFloat)
+         return (bool)f;
+      if (isStringType())
+         return dAtob(s);
+      return dAtob(getConsoleData());
+   }
+
+   TORQUE_FORCEINLINE void setFloat(const F64 val)
+   {
+      AssertFatal(type == ConsoleValueType::cvNone, "Attempted to access ConsoleValue when it has no value!");
+      cleanupData();
+      type = ConsoleValueType::cvFloat;
+      f = val;
+   }
+
+   TORQUE_FORCEINLINE void setInt(const S64 val)
+   {
+      cleanupData();
+      type = ConsoleValueType::cvInteger;
+      i = val;
+   }
+
+   TORQUE_FORCEINLINE void setString(const char* val, S32 len)
+   {
+      cleanupData();
+
+      type = ConsoleValueType::cvString;
+
+      s = (char*)dMalloc(len + 1);
+      s[len] = 0x0;
+      dStrcpy(s, val, len);
+   }
+
+   TORQUE_FORCEINLINE void setBool(const bool val)
+   {
+      cleanupData();
+      type = ConsoleValueType::cvInteger;
+      i = (int)val;
+   }
+
+   TORQUE_FORCEINLINE void setStringTableEntry(StringTableEntry val)
+   {
+      cleanupData();
+      type = ConsoleValueType::cvSTEntry;
+      s = const_cast<char*>(val);
+   }
+
+   TORQUE_FORCEINLINE void setConsoleData(S32 consoleType, void* dataPtr, EnumTable* enumTable)
+   {
+      cleanupData();
+      type = ConsoleValueType::cvSTEntry;
+      ct = new ConsoleValueConsoleType{ dataPtr, enumTable };
+   }
+
+   TORQUE_FORCEINLINE S32 getType() const
+   {
+      return type;
+   }
+
+   static void init();
+   static S32 getConstantBufferCount() { return (S32)ConversionBufferSize / StringSize; }
+};
 
 // Transparently converts ConsoleValue[] to const char**
-class StringStackWrapper
+class ConsoleValueToStringArrayWrapper
 {
 public:
    const char **argv;
-   int argc;
+   S32 argc;
 
-   StringStackWrapper(int targc, ConsoleValueRef targv[]);
-   ~StringStackWrapper();
+   ConsoleValueToStringArrayWrapper(int targc, ConsoleValue* targv);
+   ~ConsoleValueToStringArrayWrapper();
 
-   const char* operator[](int idx) { return argv[idx]; }
+   const char* operator[](S32 idx) { return argv[idx]; }
    operator const char**() { return argv; }
 
-   int count() { return argc; }
+   S32 count() { return argc; }
 };
 
 // Transparently converts const char** to ConsoleValue
-class StringStackConsoleWrapper
+class StringArrayToConsoleValueWrapper
 {
 public:
-   ConsoleValue *argvValue;
-   ConsoleValueRef *argv;
-   int argc;
+   ConsoleValue *argv;
+   S32 argc;
 
-   StringStackConsoleWrapper(int targc, const char **targv);
-   ~StringStackConsoleWrapper();
+   StringArrayToConsoleValueWrapper(int targc, const char **targv);
+   ~StringArrayToConsoleValueWrapper();
 
-   ConsoleValueRef& operator[](int idx) { return argv[idx]; }
-   operator ConsoleValueRef*() { return argv; }
+   ConsoleValue& operator[](int idx) { return argv[idx]; }
+   operator ConsoleValue*() { return argv; }
 
-   int count() { return argc; }
+   S32 count() { return argc; }
 };
 
 /// @defgroup console_callbacks Scripting Engine Callbacks
@@ -319,11 +381,11 @@ public:
 /// @{
 
 ///
-typedef const char * (*StringCallback)(SimObject *obj, S32 argc, ConsoleValueRef argv[]);
-typedef S32(*IntCallback)(SimObject *obj, S32 argc, ConsoleValueRef argv[]);
-typedef F32(*FloatCallback)(SimObject *obj, S32 argc, ConsoleValueRef argv[]);
-typedef void(*VoidCallback)(SimObject *obj, S32 argc, ConsoleValueRef argv[]); // We have it return a value so things don't break..
-typedef bool(*BoolCallback)(SimObject *obj, S32 argc, ConsoleValueRef argv[]);
+typedef const char * (*StringCallback)(SimObject *obj, S32 argc, ConsoleValue argv[]);
+typedef S32(*IntCallback)(SimObject *obj, S32 argc, ConsoleValue argv[]);
+typedef F32(*FloatCallback)(SimObject *obj, S32 argc, ConsoleValue argv[]);
+typedef void(*VoidCallback)(SimObject *obj, S32 argc, ConsoleValue argv[]); // We have it return a value so things don't break..
+typedef bool(*BoolCallback)(SimObject *obj, S32 argc, ConsoleValue argv[]);
 
 typedef void(*ConsumerCallback)(U32 level, const char *consoleLine);
 /// @}
@@ -786,8 +848,8 @@ namespace Con
    /// char* result = execute(2, argv);
    /// @endcode
    /// NOTE: this function restores the console stack on return.
-   ConsoleValueRef execute(S32 argc, const char* argv[]);
-   ConsoleValueRef execute(S32 argc, ConsoleValueRef argv[]);
+   ConsoleValue execute(S32 argc, const char* argv[]);
+   ConsoleValue execute(S32 argc, ConsoleValue argv[]);
 
    /// Call a Torque Script member function of a SimObject from C/C++ code.
    /// @param object    Object on which to execute the method call.
@@ -802,8 +864,8 @@ namespace Con
    /// char* result = execute(mysimobject, 3, argv);
    /// @endcode
    /// NOTE: this function restores the console stack on return.
-   ConsoleValueRef execute(SimObject *object, S32 argc, const char* argv[], bool thisCallOnly = false);
-   ConsoleValueRef execute(SimObject *object, S32 argc, ConsoleValueRef argv[], bool thisCallOnly = false);
+   ConsoleValue execute(SimObject *object, S32 argc, const char* argv[], bool thisCallOnly = false);
+   ConsoleValue execute(SimObject *object, S32 argc, ConsoleValue argv[], bool thisCallOnly = false);
 
    /// Executes a script file and compiles it for use in script.
    ///
@@ -821,13 +883,13 @@ namespace Con
    /// @param  echo     Should we echo the string to the console?
    /// @param  fileName Indicate what file this code is coming from; used in error reporting and such.
    /// NOTE: This function restores the console stack on return.
-   ConsoleValueRef evaluate(const char* string, bool echo = false, const char *fileName = NULL);
+   ConsoleValue evaluate(const char* string, bool echo = false, const char *fileName = NULL);
 
    /// Evaluate an arbitrary line of script.
    ///
    /// This wraps dVsprintf(), so you can substitute parameters into the code being executed.
    /// NOTE: This function restores the console stack on return.
-   ConsoleValueRef evaluatef(const char* string, ...);
+   ConsoleValue evaluatef(const char* string, ...);
 
    /// @}
 
@@ -915,10 +977,10 @@ namespace Con
    /// @see _EngineConsoleExecCallbackHelper
    ///
    template<typename R, typename ...ArgTs>
-   ConsoleValueRef executef(R r, ArgTs ...argTs)
+   ConsoleValue executef(R r, ArgTs ...argTs)
    {
       _EngineConsoleExecCallbackHelper<R> callback(r);
-      return callback.template call<ConsoleValueRef>(argTs...);
+      return std::move(callback.template call<ConsoleValue>(argTs...));
    }
    /// }
 };

+ 3 - 3
Engine/source/console/engineAPI.h

@@ -864,7 +864,7 @@ public:
       (Vector<const char*>* vec)                                                                                                 \
    {                                                                                                                             \
       _CHECK_ENGINE_INITIALIZED( name, returnType );                                                                             \
-      StringStackConsoleWrapper args(vec->size(), vec->address());                                                               \
+      StringArrayToConsoleValueWrapper args(vec->size(), vec->address());                                                               \
       return EngineTypeTraits< returnType >::ReturnValue(                                                                        \
          _fn ## name ## impl(NULL, args.count(), args)                                                                           \
       );                                                                                                                         \
@@ -895,7 +895,7 @@ public:
       (className* object, Vector<const char*>* vec)                                                                              \
    {                                                                                                                             \
       _CHECK_ENGINE_INITIALIZED( name, returnType );                                                                             \
-      StringStackConsoleWrapper args(vec->size(), vec->address());                                                               \
+      StringArrayToConsoleValueWrapper args(vec->size(), vec->address());                                                               \
       _ ## className ## name ## frame frame {};                                                                                  \
       frame.object = static_cast< className* >( object );                                                                        \
       return EngineTypeTraits< returnType >::ReturnValue(                                                                        \
@@ -1226,7 +1226,7 @@ public:
 template<typename P1> struct _EngineConsoleExecCallbackHelper : public _BaseEngineConsoleCallbackHelper
 {
 private:
-   using Helper = engineAPI::detail::MarshallHelpers<ConsoleValueRef>;
+   using Helper = engineAPI::detail::MarshallHelpers<ConsoleValue>;
 public:
 
    _EngineConsoleExecCallbackHelper( SimObject* pThis )

+ 0 - 2
Engine/source/console/simEvents.h

@@ -83,8 +83,6 @@ public:
    virtual void process(SimObject *object)=0;
 };
 
-class ConsoleValueRef;
-
 /// Implementation of schedule() function.
 ///
 /// This allows you to set a console function to be

+ 1 - 1
Engine/source/gui/editor/guiFilterCtrl.cpp

@@ -83,7 +83,7 @@ DefineEngineStringlyVariadicMethod( GuiFilterCtrl, setValue, void, 3, 20, "(f1,
 {
    Filter filter;
 
-   StringStackWrapper args(argc - 2, argv + 2);
+   ConsoleValueToStringArrayWrapper args(argc - 2, argv + 2);
 
    filter.set(args.count(), args);
 	object->set(filter);

+ 10 - 1
Engine/source/platform/types.visualc.h

@@ -102,8 +102,17 @@ typedef unsigned _int64 U64;
 
 // disable warning caused by memory layer
 // see msdn.microsoft.com "Compiler Warning (level 1) C4291" for more details
-#pragma warning(disable: 4291) 
+#pragma warning(disable: 4291)
 
+#define TORQUE_FORCEINLINE __forceinline
+
+#if __cplusplus >= 201703L
+#define TORQUE_CASE_FALLTHROUGH [[fallthrough]];
+#define TORQUE_UNLIKELY [[unlikely]]
+#else
+#define TORQUE_CASE_FALLTHROUGH __fallthrough
+#define TORQUE_UNLIKELY
+#endif
 
 #endif // INCLUDED_TYPES_VISUALC_H
 

+ 2 - 2
Engine/source/sim/actionMap.cpp

@@ -2080,7 +2080,7 @@ static ConsoleDocFragment _ActionMapbind2(
 DefineEngineStringlyVariadicMethod( ActionMap, bind, bool, 5, 10, "actionMap.bind( device, action, [modifier, spec, mod...], command )"
            "@hide")
 {
-   StringStackWrapper args(argc - 2, argv + 2);
+   ConsoleValueToStringArrayWrapper args(argc - 2, argv + 2);
    return object->processBind( args.count(), args, NULL );
 }
 
@@ -2136,7 +2136,7 @@ DefineEngineStringlyVariadicMethod( ActionMap, bindObj, bool, 6, 11, "(device, a
       return false;
    }
 
-   StringStackWrapper args(argc - 3, argv + 2);
+   ConsoleValueToStringArrayWrapper args(argc - 3, argv + 2);
    return object->processBind( args.count(), args, simObject );
 }