diff --git a/indra/newview/rlvcommon.cpp b/indra/newview/rlvcommon.cpp
index 2dad3a4d00123f9be09e85bab010c8a24f4a0d85..e9f2d2fc69b91e8f035707c297f282f87a543338 100644
--- a/indra/newview/rlvcommon.cpp
+++ b/indra/newview/rlvcommon.cpp
@@ -439,6 +439,11 @@ std::string RlvStrings::getVersionNum(const LLUUID& idRlvObject)
 		(!fCompatMode) ? RLV_VERSION_PATCH : RLV_VERSION_PATCH_COMPAT, (!fCompatMode) ? RLV_VERSION_BUILD : RLV_VERSION_BUILD_COMPAT);
 }
 
+std::string RlvStrings::getVersionImplNum()
+{
+	return llformat("%d%02d%02d%02d", RLVa_VERSION_MAJOR, RLVa_VERSION_MAJOR, RLVa_VERSION_PATCH, RLVa_IMPL_ID);
+}
+
 // Checked: 2011-11-08 (RLVa-1.5.0)
 bool RlvStrings::hasString(const std::string& strStringName, bool fCheckCustom)
 {
diff --git a/indra/newview/rlvcommon.h b/indra/newview/rlvcommon.h
index caaab5ef20bfe7e69f91f713147226473cb4e4a1..82fca44f91b6772692f6708f4ee3a20e9d3a831d 100644
--- a/indra/newview/rlvcommon.h
+++ b/indra/newview/rlvcommon.h
@@ -151,6 +151,7 @@ class RlvStrings
 	static const std::string& getStringMapPath() { return m_StringMapPath; }
 	static std::string        getVersion(const LLUUID& idRlvObject, bool fLegacy = false);
 	static std::string        getVersionAbout();
+	static std::string        getVersionImplNum();
 	static std::string        getVersionNum(const LLUUID& idRlvObject);
 	static bool               hasString(const std::string& strStringName, bool fCheckCustom = false);
 	static void               setCustomString(const std::string& strStringName, const std::string& strStringValue);
diff --git a/indra/newview/rlvdefines.h b/indra/newview/rlvdefines.h
index 4bf56bd886f5148b7d4d2f80e8e9c8694c339ecd..f43a332f9f50dd3103ece3409aa4c9ba3cfbad84 100644
--- a/indra/newview/rlvdefines.h
+++ b/indra/newview/rlvdefines.h
@@ -37,6 +37,7 @@ const S32 RLV_VERSION_BUILD_COMPAT = 0;
 const S32 RLVa_VERSION_MAJOR = 2;
 const S32 RLVa_VERSION_MINOR = 2;
 const S32 RLVa_VERSION_PATCH = 3;
+const S32 RLVa_IMPL_ID = 13;
 
 // Uncomment before a final release
 //#define RLV_RELEASE
diff --git a/indra/newview/rlvhandler.cpp b/indra/newview/rlvhandler.cpp
index 8f036751b875b230e004e773ad69a3d34fce10f7..d64bcabeb46d599df4a39bada62eeebd32816ee7 100644
--- a/indra/newview/rlvhandler.cpp
+++ b/indra/newview/rlvhandler.cpp
@@ -439,42 +439,46 @@ bool RlvHandler::notifyCommandHandlers(rlvExtCommandHandler f, const RlvCommand&
 }
 
 // Checked: 2009-11-25 (RLVa-1.1.0f) | Modified: RLVa-1.1.0f
-ERlvCmdRet RlvHandler::processCommand(const RlvCommand& rlvCmd, bool fFromObj)
+ERlvCmdRet RlvHandler::processCommand(std::reference_wrapper<const RlvCommand> rlvCmd, bool fFromObj)
 {
-	RLV_DEBUGS << "[" << rlvCmd.getObjectID() << "]: " << rlvCmd.asString() << RLV_ENDL;
-
-	if ( (isBlockedObject(rlvCmd.getObjectID())) && (RLV_TYPE_REMOVE != rlvCmd.getParamType()) && (RLV_TYPE_CLEAR != rlvCmd.getParamType()) )
-	{
-		RLV_DEBUGS << "\t-> blocked object" << RLV_ENDL;
-		return RLV_RET_FAILED_BLOCKED;
-	}
-	if (!rlvCmd.isValid())
 	{
-		RLV_DEBUGS << "\t-> invalid syntax" << RLV_ENDL;
-		return RLV_RET_FAILED_SYNTAX;
-	}
-	if (rlvCmd.isBlocked())
-	{
-		RLV_DEBUGS << "\t-> blocked command" << RLV_ENDL;
-		return RLV_RET_FAILED_DISABLED;
+		const RlvCommand& rlvCmdTmp = rlvCmd; // Reference to the temporary with limited variable scope since we don't want it to leak below
+
+		RLV_DEBUGS << "[" << rlvCmdTmp.getObjectID() << "]: " << rlvCmdTmp.asString() << RLV_ENDL;
+
+		if ( (isBlockedObject(rlvCmdTmp.getObjectID())) && (RLV_TYPE_REMOVE != rlvCmdTmp.getParamType()) && (RLV_TYPE_CLEAR != rlvCmdTmp.getParamType()) )
+		{
+			RLV_DEBUGS << "\t-> blocked object" << RLV_ENDL;
+			return RLV_RET_FAILED_BLOCKED;
+		}
+		if (!rlvCmdTmp.isValid())
+		{
+			RLV_DEBUGS << "\t-> invalid syntax" << RLV_ENDL;
+			return RLV_RET_FAILED_SYNTAX;
+		}
+		if (rlvCmdTmp.isBlocked())
+		{
+			RLV_DEBUGS << "\t-> blocked command" << RLV_ENDL;
+			return RLV_RET_FAILED_DISABLED;
+		}
 	}
 
 	// Using a stack for executing commands solves a few problems:
 	//   - if we passed RlvObject::m_idObj for idObj somewhere and process a @clear then idObj points to invalid/cleared memory at the end
 	//   - if command X triggers command Y along the way then getCurrentCommand()/getCurrentObject() still return Y even when finished
-	m_CurCommandStack.push(&rlvCmd); m_CurObjectStack.push(rlvCmd.getObjectID());
+	m_CurCommandStack.push(rlvCmd); m_CurObjectStack.push(rlvCmd.get().getObjectID());
 	const LLUUID& idCurObj = m_CurObjectStack.top();
 
 	ERlvCmdRet eRet = RLV_RET_UNKNOWN;
-	switch (rlvCmd.getParamType())
+	switch (rlvCmd.get().getParamType())
 	{
 		case RLV_TYPE_ADD:		// Checked: 2009-11-26 (RLVa-1.1.0f) | Modified: RLVa-1.1.0f
 			{
-				if ( (m_Behaviours[rlvCmd.getBehaviourType()]) && 
-					 ( (RLV_BHVR_SETCAM == rlvCmd.getBehaviourType()) || (RLV_BHVR_SETDEBUG == rlvCmd.getBehaviourType()) || (RLV_BHVR_SETENV == rlvCmd.getBehaviourType()) ) )
+				ERlvBehaviour eBhvr = rlvCmd.get().getBehaviourType();
+				if ( (m_Behaviours[eBhvr]) && ( (RLV_BHVR_SETCAM == eBhvr) || (RLV_BHVR_SETDEBUG == eBhvr) || (RLV_BHVR_SETENV == eBhvr) ) )
 				{
 					// Some restrictions can only be held by one single object to avoid deadlocks
-					RLV_DEBUGS << "\t- " << rlvCmd.getBehaviour() << " is already set by another object => discarding" << RLV_ENDL;
+					RLV_DEBUGS << "\t- " << rlvCmd.get().getBehaviour() << " is already set by another object => discarding" << RLV_ENDL;
 					eRet = RLV_RET_FAILED_LOCK;
 					break;
 				}
@@ -482,14 +486,14 @@ ERlvCmdRet RlvHandler::processCommand(const RlvCommand& rlvCmd, bool fFromObj)
 				rlv_object_map_t::iterator itObj = m_Objects.find(idCurObj); bool fAdded = false;
 				if (itObj != m_Objects.end())
 				{
-					RlvObject& rlvObj = itObj->second;
-					fAdded = rlvObj.addCommand(rlvCmd);
+					// Add the command to an existing object
+					rlvCmd = itObj->second.addCommand(rlvCmd, fAdded);
 				}
 				else
 				{
-					RlvObject rlvObj(idCurObj);
-					fAdded = rlvObj.addCommand(rlvCmd);
-					itObj = m_Objects.insert(std::pair<LLUUID, RlvObject>(idCurObj, rlvObj)).first;
+					// Create a new RLV object and then add the command to it (and grab its reference)
+					itObj = m_Objects.insert(std::pair<LLUUID, RlvObject>(idCurObj, RlvObject(idCurObj))).first;
+					rlvCmd = itObj->second.addCommand(rlvCmd, fAdded);
 				}
 
 				RLV_DEBUGS << "\t- " << ( (fAdded) ? "adding behaviour" : "skipping duplicate" ) << RLV_ENDL;
@@ -564,12 +568,13 @@ ERlvCmdRet RlvHandler::processCommand(const RlvCommand& rlvCmd, bool fFromObj)
 // Checked: 2009-11-25 (RLVa-1.1.0f) | Modified: RLVa-1.1.0f
 ERlvCmdRet RlvHandler::processCommand(const LLUUID& idObj, const std::string& strCommand, bool fFromObj)
 {
+	const RlvCommand rlvCmd(idObj, strCommand);
 	if (STATE_STARTED != LLStartUp::getStartupState())
 	{
-		m_Retained.push_back(RlvCommand(idObj, strCommand));
+		m_Retained.push_back(rlvCmd);
 		return RLV_RET_RETAINED;
 	}
-	return processCommand(RlvCommand(idObj, strCommand), fFromObj);
+	return processCommand(std::ref(rlvCmd), fFromObj);
 }
 
 // Checked: 2010-02-27 (RLVa-1.2.0a) | Modified: RLVa-1.1.0f
@@ -584,7 +589,7 @@ void RlvHandler::processRetainedCommands(ERlvBehaviour eBhvrFilter /*=RLV_BHVR_U
 		if ( ((RLV_BHVR_UNKNOWN == eBhvrFilter) || (rlvCmd.getBehaviourType() == eBhvrFilter)) && 
 			 ((RLV_TYPE_UNKNOWN == eTypeFilter) || (rlvCmd.getParamType() == eTypeFilter)) )
 		{
-			processCommand(rlvCmd, true);
+			processCommand(std::ref(rlvCmd), true);
 			m_Retained.erase(itCurCmd);
 		}
 	}
@@ -3172,7 +3177,10 @@ ERlvCmdRet RlvHandler::processReplyCommand(const RlvCommand& rlvCmd) const
 			break;
 		case RLV_BHVR_VERSIONNUM:		// @versionnum=<channel>				- Checked: 2010-03-27 (RLVa-1.4.0a) | Added: RLVa-1.0.4b
 			// NOTE: RLV will respond even if there's an option
-			strReply = RlvStrings::getVersionNum(rlvCmd.getObjectID());
+			if (!rlvCmd.hasOption())
+				strReply = RlvStrings::getVersionNum(rlvCmd.getObjectID());
+			else if ("impl" == rlvCmd.getOption())
+				strReply = RlvStrings::getVersionImplNum();
 			break;
 		case RLV_BHVR_GETATTACH:		// @getattach[:<layer>]=<channel>
 			eRet = onGetAttach(rlvCmd, strReply);
diff --git a/indra/newview/rlvhandler.h b/indra/newview/rlvhandler.h
index a6e596c724215a863793f223abdc95b909ebfed1..32eda851371a36096b94575255de537a1f430835 100644
--- a/indra/newview/rlvhandler.h
+++ b/indra/newview/rlvhandler.h
@@ -133,7 +133,7 @@ class RlvHandler : public LLOldEvents::LLSimpleListener, public LLParticularGrou
 	bool       processIMQuery(const LLUUID& idSender, const std::string& strCommand);
 
 	// Returns a pointer to the currently executing command (do *not* save this pointer)
-	const RlvCommand* getCurrentCommand() const { return (!m_CurCommandStack.empty()) ? m_CurCommandStack.top() : NULL; }
+	const RlvCommand* getCurrentCommand() const { return (!m_CurCommandStack.empty()) ? &m_CurCommandStack.top().get() : nullptr; }
 	// Returns the UUID of the object we're currently executing a command for
 	const LLUUID&     getCurrentObject() const	{ return (!m_CurObjectStack.empty()) ? m_CurObjectStack.top() : LLUUID::null; }
 
@@ -204,7 +204,7 @@ class RlvHandler : public LLOldEvents::LLSimpleListener, public LLParticularGrou
 	 * Command processing
 	 */
 protected:
-	ERlvCmdRet processCommand(const RlvCommand& rlvCmd, bool fFromObj);
+	ERlvCmdRet processCommand(std::reference_wrapper<const RlvCommand> rlvCmdRef, bool fFromObj);
 	ERlvCmdRet processClearCommand(const RlvCommand& rlvCmd);
 
 	// Command handlers (RLV_TYPE_ADD and RLV_TYPE_CLEAR)
@@ -245,7 +245,7 @@ class RlvHandler : public LLOldEvents::LLSimpleListener, public LLParticularGrou
 	rlv_command_list_t    m_Retained;
 	RlvGCTimer*           m_pGCTimer;
 
-	std::stack<const RlvCommand*> m_CurCommandStack;// Convenience (see @tpto)
+	std::stack<std::reference_wrapper<const RlvCommand>> m_CurCommandStack; // Convenience (see @tpto)
 	std::stack<LLUUID>    m_CurObjectStack;			// Convenience (see @tpto)
 
 	rlv_behaviour_signal_t m_OnBehaviour;
diff --git a/indra/newview/rlvhelper.cpp b/indra/newview/rlvhelper.cpp
index 16af827ddecb3dac050bfa795c0b24f87af7ce27..2a0ecf6d972008e83316a0ef99d3dacf48f7a358 100644
--- a/indra/newview/rlvhelper.cpp
+++ b/indra/newview/rlvhelper.cpp
@@ -645,8 +645,9 @@ RlvCommand::RlvCommand(const LLUUID& idObj, const std::string& strCommand)
 }
 
 RlvCommand::RlvCommand(const RlvCommand& rlvCmd, ERlvParamType eParamType)
-	: m_fValid(rlvCmd.m_fValid), m_idObj(rlvCmd.m_idObj), m_strBehaviour(rlvCmd.m_strBehaviour), m_pBhvrInfo(rlvCmd.m_pBhvrInfo),
-	  m_eParamType( (RLV_TYPE_UNKNOWN == eParamType) ? rlvCmd.m_eParamType : eParamType),m_fStrict(rlvCmd.m_fStrict), m_strOption(rlvCmd.m_strOption), m_strParam(rlvCmd.m_strParam), m_fRefCounted(false)
+	: m_fValid(rlvCmd.m_fValid), m_idObj(rlvCmd.m_idObj), m_strBehaviour(rlvCmd.m_strBehaviour), m_pBhvrInfo(rlvCmd.m_pBhvrInfo)
+	, m_eParamType( (RLV_TYPE_UNKNOWN == eParamType) ? rlvCmd.m_eParamType : eParamType),m_fStrict(rlvCmd.m_fStrict), m_strOption(rlvCmd.m_strOption)
+	, m_strParam(rlvCmd.m_strParam), m_fRefCounted(rlvCmd.m_fRefCounted)
 {
 }
 
@@ -992,7 +993,7 @@ RlvObject::RlvObject(const LLUUID& idObj) : m_idObj(idObj), m_nLookupMisses(0)
 	m_idRoot = (pObj) ? pObj->getRootEdit()->getID() : LLUUID::null;
 }
 
-bool RlvObject::addCommand(const RlvCommand& rlvCmd)
+const RlvCommand& RlvObject::addCommand(const RlvCommand& rlvCmd, bool& fAdded)
 {
 	RLV_ASSERT(RLV_TYPE_ADD == rlvCmd.getParamType());
 
@@ -1002,14 +1003,15 @@ bool RlvObject::addCommand(const RlvCommand& rlvCmd)
 		if ( (itCmd->getBehaviour() == rlvCmd.getBehaviour()) && (itCmd->getOption() == rlvCmd.getOption()) && 
 			 (itCmd->isStrict() == rlvCmd.isStrict() ) )
 		{
-			return false;
+			fAdded = false;
+			return *itCmd;
 		}
 	}
 
 	// Now that we know it's not a duplicate, add it to the end of the list
 	m_Commands.push_back(rlvCmd);
-
-	return true;
+	fAdded = true;
+	return m_Commands.back();
 }
 
 bool RlvObject::removeCommand(const RlvCommand& rlvCmd)
diff --git a/indra/newview/rlvhelper.h b/indra/newview/rlvhelper.h
index 7269e4b678979705c85189ca4539a99befb07323..cbe79ec57a0347790b4227ab014eee427933df1e 100644
--- a/indra/newview/rlvhelper.h
+++ b/indra/newview/rlvhelper.h
@@ -434,8 +434,8 @@ class RlvObject
 	 * Member functions
 	 */
 public:
-	bool addCommand(const RlvCommand& rlvCmd);
-	bool removeCommand(const RlvCommand& rlvCmd);
+	const RlvCommand& addCommand(const RlvCommand& rlvCmd, bool& fAdded);
+	bool              removeCommand(const RlvCommand& rlvCmd);
 
 	std::string getStatusString(const std::string& strFilter, const std::string& strSeparator) const;
 	bool        hasBehaviour(ERlvBehaviour eBehaviour, bool fStrictOnly) const;