Procházet zdrojové kódy

Mono manager now properly cleans up script meta-data on assembly unload
Script resource creation from native code no longer incorrectly creates two interop objects per resource

BearishSun před 10 roky
rodič
revize
1b0786cf45
37 změnil soubory, kde provedl 205 přidání a 26 odebrání
  1. 1 8
      BansheeMono/Include/BsMonoManager.h
  2. 12 11
      BansheeMono/Source/BsMonoManager.cpp
  3. 1 1
      MBansheeEngine/ManagedResource.cs
  4. 7 0
      MBansheeEngine/Material.cs
  5. 1 1
      MBansheeEngine/PlainText.cs
  6. 6 0
      MBansheeEngine/ScriptCode.cs
  7. 5 0
      SBansheeEngine/Include/BsScriptFont.h
  8. 8 1
      SBansheeEngine/Include/BsScriptGUISkin.h
  9. 5 0
      SBansheeEngine/Include/BsScriptManagedResource.h
  10. 5 0
      SBansheeEngine/Include/BsScriptMaterial.h
  11. 5 0
      SBansheeEngine/Include/BsScriptMesh.h
  12. 5 0
      SBansheeEngine/Include/BsScriptPlainText.h
  13. 5 0
      SBansheeEngine/Include/BsScriptPrefab.h
  14. 6 0
      SBansheeEngine/Include/BsScriptScriptCode.h
  15. 5 0
      SBansheeEngine/Include/BsScriptShader.h
  16. 5 0
      SBansheeEngine/Include/BsScriptShaderInclude.h
  17. 5 0
      SBansheeEngine/Include/BsScriptSpriteTexture.h
  18. 8 1
      SBansheeEngine/Include/BsScriptStringTable.h
  19. 5 0
      SBansheeEngine/Include/BsScriptTexture2D.h
  20. 5 0
      SBansheeEngine/Include/BsScriptTexture3D.h
  21. 5 0
      SBansheeEngine/Include/BsScriptTextureCube.h
  22. 5 0
      SBansheeEngine/Source/BsScriptFont.cpp
  23. 10 0
      SBansheeEngine/Source/BsScriptGUISkin.cpp
  24. 9 2
      SBansheeEngine/Source/BsScriptManagedResource.cpp
  25. 10 0
      SBansheeEngine/Source/BsScriptMaterial.cpp
  26. 5 0
      SBansheeEngine/Source/BsScriptMesh.cpp
  27. 5 0
      SBansheeEngine/Source/BsScriptPlainText.cpp
  28. 5 0
      SBansheeEngine/Source/BsScriptPrefab.cpp
  29. 1 1
      SBansheeEngine/Source/BsScriptResourceManager.cpp
  30. 5 0
      SBansheeEngine/Source/BsScriptScriptCode.cpp
  31. 5 0
      SBansheeEngine/Source/BsScriptShader.cpp
  32. 5 0
      SBansheeEngine/Source/BsScriptShaderInclude.cpp
  33. 5 0
      SBansheeEngine/Source/BsScriptSpriteTexture.cpp
  34. 10 0
      SBansheeEngine/Source/BsScriptStringTable.cpp
  35. 5 0
      SBansheeEngine/Source/BsScriptTexture2D.cpp
  36. 5 0
      SBansheeEngine/Source/BsScriptTexture3D.cpp
  37. 5 0
      SBansheeEngine/Source/BsScriptTextureCube.cpp

+ 1 - 8
BansheeMono/Include/BsMonoManager.h

@@ -33,13 +33,6 @@ namespace BansheeEngine
 		 */
 		MonoAssembly& loadAssembly(const String& path, const String& name);
 
-		/**
-		 * @brief	Unloads a previously loaded assembly.
-		 *
-		 * @note	You must perform JIT cleanup before unloading assemblies.
-		 */
-		void unloadAssembly(MonoAssembly& assembly);
-
 		/**
 		 * @brief	Searches all loaded assemblies for the specified class.
 		 */
@@ -103,7 +96,7 @@ namespace BansheeEngine
 		/**
 		 * @brief	Returns a list of all types that will be initializes with their assembly gets loaded.
 		 */
-		static UnorderedMap<String, Vector<ScriptMeta*>>& getTypesToInitialize()
+		static UnorderedMap<String, Vector<ScriptMeta*>>& getScriptMetaData()
 		{
 			static UnorderedMap<String, Vector<ScriptMeta*>> mTypesToInitialize;
 			return mTypesToInitialize;

+ 12 - 11
BansheeMono/Source/BsMonoManager.cpp

@@ -97,15 +97,6 @@ namespace BansheeEngine
 		return *assembly;
 	}
 
-	void MonoManager::unloadAssembly(MonoAssembly& assembly)
-	{
-		::MonoAssembly* monoAssembly = assembly.mMonoAssembly;
-		assembly.unload();
-
-		if(monoAssembly)
-			mono_assembly_close(monoAssembly);
-	}
-
 	void MonoManager::initializeAssembly(MonoAssembly& assembly)
 	{
 		if (!assembly.mIsLoaded)
@@ -113,7 +104,7 @@ namespace BansheeEngine
 			assembly.load(mScriptDomain);
 
 			// Fully initialize all types that use this assembly
-			Vector<ScriptMeta*>& mTypeMetas = getTypesToInitialize()[assembly.mName];
+			Vector<ScriptMeta*>& mTypeMetas = getScriptMetaData()[assembly.mName];
 			for (auto& meta : mTypeMetas)
 			{
 				meta->scriptClass = assembly.getClass(meta->ns, meta->name);
@@ -160,7 +151,7 @@ namespace BansheeEngine
 
 	void MonoManager::registerScriptType(ScriptMeta* metaData)
 	{
-		Vector<ScriptMeta*>& mMetas = getTypesToInitialize()[metaData->assembly];
+		Vector<ScriptMeta*>& mMetas = getScriptMetaData()[metaData->assembly];
 		mMetas.push_back(metaData);
 	}
 
@@ -211,8 +202,18 @@ namespace BansheeEngine
 		}
 
 		for (auto& assemblyEntry : mAssemblies)
+		{
 			assemblyEntry.second->unload();
 
+			// Metas hold references to various assembly objects that were just deleted, so clear them
+			Vector<ScriptMeta*>& typeMetas = getScriptMetaData()[assemblyEntry.first];
+			for (auto& entry : typeMetas)
+			{
+				entry->scriptClass = nullptr;
+				entry->thisPtrField = nullptr;
+			}
+		}
+
 		mAssemblies.clear();
 		mIsCoreLoaded = false;
 	}

+ 1 - 1
MBansheeEngine/ManagedResource.cs

@@ -13,7 +13,7 @@ namespace BansheeEngine
     public class ManagedResource : Resource
     {
         /// <summary>
-        /// Constructo for internal use by the runtime.
+        /// Constructor for internal use by the runtime.
         /// </summary>
         protected ManagedResource()
         { }

+ 7 - 0
MBansheeEngine/Material.cs

@@ -20,6 +20,13 @@ namespace BansheeEngine
             Internal_CreateInstance(this, IntPtr.Zero);
         }
 
+        /// <summary>
+        /// Constructor for internal runtime use only.
+        /// </summary>
+        /// <param name="dummy">Dummy parameter to differentiate it from other constructors.</param>
+        private Material(bool dummy)
+        { }
+
         /// <summary>
         /// Creates a new material with the specified shader.
         /// </summary>

+ 1 - 1
MBansheeEngine/PlainText.cs

@@ -9,7 +9,7 @@ namespace BansheeEngine
     public class PlainText : Resource
     {
         /// <summary>
-        /// Constructor used internally by the runtime.
+        /// Constructor for internal use by the runtime.
         /// </summary>
         private PlainText()
         { }

+ 6 - 0
MBansheeEngine/ScriptCode.cs

@@ -8,6 +8,12 @@ namespace BansheeEngine
     /// </summary>
     public class ScriptCode : Resource
     {
+        /// <summary>
+        /// Constructor for internal use by the runtime.
+        /// </summary>
+        private ScriptCode()
+        { }
+
         /// <summary>
         /// Script code text.
         /// </summary>

+ 5 - 0
SBansheeEngine/Include/BsScriptFont.h

@@ -20,6 +20,11 @@ namespace BansheeEngine
 
 		ScriptFont(MonoObject* instance, const HFont& font);
 
+		/**
+		 * @brief	Creates an empty, uninitialized managed instance of the resource interop object.
+		 */
+		static MonoObject* createInstance();
+
 		/************************************************************************/
 		/* 								CLR HOOKS						   		*/
 		/************************************************************************/

+ 8 - 1
SBansheeEngine/Include/BsScriptGUISkin.h

@@ -13,9 +13,16 @@ namespace BansheeEngine
 	public:
 		SCRIPT_OBJ(ENGINE_ASSEMBLY, "BansheeEngine", "GUISkin")
 
+	private:
+		friend class ScriptResourceManager;
+
 		ScriptGUISkin(MonoObject* instance, const HGUISkin& skin);
 
-	private:
+		/**
+		 * @brief	Creates an empty, uninitialized managed instance of the resource interop object.
+		 */
+		static MonoObject* createInstance();
+
 		/************************************************************************/
 		/* 								CLR HOOKS						   		*/
 		/************************************************************************/

+ 5 - 0
SBansheeEngine/Include/BsScriptManagedResource.h

@@ -53,6 +53,11 @@ namespace BansheeEngine
 		 */
 		void _onManagedInstanceDeleted() override;
 
+		/**
+		 * @brief	Creates an empty, uninitialized managed instance of the resource interop object.
+		 */
+		static MonoObject* createInstance();
+
 		HManagedResource mResource;
 		String mNamespace;
 		String mType;

+ 5 - 0
SBansheeEngine/Include/BsScriptMaterial.h

@@ -25,6 +25,11 @@ namespace BansheeEngine
 
 		ScriptMaterial(MonoObject* instance, const HMaterial& material);
 
+		/**
+		 * @brief	Creates an empty, uninitialized managed instance of the resource interop object.
+		 */
+		static MonoObject* createInstance();
+
 		/************************************************************************/
 		/* 								CLR HOOKS						   		*/
 		/************************************************************************/

+ 5 - 0
SBansheeEngine/Include/BsScriptMesh.h

@@ -87,6 +87,11 @@ namespace BansheeEngine
 		 */
 		static Vector<SubMesh> monoToNativeSubMeshes(MonoArray* subMeshes);
 
+		/**
+		 * @brief	Creates an empty, uninitialized managed instance of the resource interop object.
+		 */
+		static MonoObject* createInstance();
+
 		/************************************************************************/
 		/* 								CLR HOOKS						   		*/
 		/************************************************************************/

+ 5 - 0
SBansheeEngine/Include/BsScriptPlainText.h

@@ -20,6 +20,11 @@ namespace BansheeEngine
 
 		ScriptPlainText(MonoObject* instance, const HPlainText& plainText);
 
+		/**
+		 * @brief	Creates an empty, uninitialized managed instance of the resource interop object.
+		 */
+		static MonoObject* createInstance();
+
 		/************************************************************************/
 		/* 								CLR HOOKS						   		*/
 		/************************************************************************/

+ 5 - 0
SBansheeEngine/Include/BsScriptPrefab.h

@@ -19,6 +19,11 @@ namespace BansheeEngine
 
 		ScriptPrefab(MonoObject* instance, const HPrefab& prefab);
 
+		/**
+		 * @brief	Creates an empty, uninitialized managed instance of the resource interop object.
+		 */
+		static MonoObject* createInstance();
+
 		/************************************************************************/
 		/* 								CLR HOOKS						   		*/
 		/************************************************************************/

+ 6 - 0
SBansheeEngine/Include/BsScriptScriptCode.h

@@ -20,12 +20,18 @@ namespace BansheeEngine
 		typedef std::pair<WString, WString> FullTypeName;
 
 		ScriptScriptCode(MonoObject* instance, const HScriptCode& scriptCode);
+
 		/**
 		 * @brief	Parses the provided C# code and finds a list of all classes
 		 *			and their namespaces. Nested classes are ignored.
 		 */
 		static Vector<FullTypeName> parseTypes(const WString& code);
 
+		/**
+		 * @brief	Creates an empty, uninitialized managed instance of the resource interop object.
+		 */
+		static MonoObject* createInstance();
+
 		/************************************************************************/
 		/* 								CLR HOOKS						   		*/
 		/************************************************************************/

+ 5 - 0
SBansheeEngine/Include/BsScriptShader.h

@@ -19,6 +19,11 @@ namespace BansheeEngine
 
 		ScriptShader(MonoObject* instance, const HShader& shader);
 
+		/**
+		 * @brief	Creates an empty, uninitialized managed instance of the resource interop object.
+		 */
+		static MonoObject* createInstance();
+
 		/************************************************************************/
 		/* 								CLR HOOKS						   		*/
 		/************************************************************************/

+ 5 - 0
SBansheeEngine/Include/BsScriptShaderInclude.h

@@ -18,5 +18,10 @@ namespace BansheeEngine
 		friend class ScriptResourceManager;
 
 		ScriptShaderInclude(MonoObject* instance, const HShaderInclude& shaderInclude);
+
+		/**
+		 * @brief	Creates an empty, uninitialized managed instance of the resource interop object.
+		 */
+		static MonoObject* createInstance();
 	};
 }

+ 5 - 0
SBansheeEngine/Include/BsScriptSpriteTexture.h

@@ -24,6 +24,11 @@ namespace BansheeEngine
 
 		ScriptSpriteTexture(MonoObject* instance, const HSpriteTexture& texture);
 
+		/**
+		 * @brief	Creates an empty, uninitialized managed instance of the resource interop object.
+		 */
+		static MonoObject* createInstance();
+
 		/************************************************************************/
 		/* 								CLR HOOKS						   		*/
 		/************************************************************************/

+ 8 - 1
SBansheeEngine/Include/BsScriptStringTable.h

@@ -14,9 +14,16 @@ namespace BansheeEngine
 	public:
 		SCRIPT_OBJ(ENGINE_ASSEMBLY, "BansheeEngine", "StringTable")
 
+	private:
+		friend class ScriptResourceManager;
+
 		ScriptStringTable(MonoObject* instance, const HStringTable& table);
 
-	private:
+		/**
+		 * @brief	Creates an empty, uninitialized managed instance of the resource interop object.
+		 */
+		static MonoObject* createInstance();
+
 		/************************************************************************/
 		/* 								CLR HOOKS						   		*/
 		/************************************************************************/

+ 5 - 0
SBansheeEngine/Include/BsScriptTexture2D.h

@@ -20,6 +20,11 @@ namespace BansheeEngine
 
 		ScriptTexture2D(MonoObject* instance, const HTexture& texture);
 
+		/**
+		 * @brief	Creates an empty, uninitialized managed instance of the resource interop object.
+		 */
+		static MonoObject* createInstance();
+
 		/************************************************************************/
 		/* 								CLR HOOKS						   		*/
 		/************************************************************************/

+ 5 - 0
SBansheeEngine/Include/BsScriptTexture3D.h

@@ -20,6 +20,11 @@ namespace BansheeEngine
 
 		ScriptTexture3D(MonoObject* instance, const HTexture& texture);
 
+		/**
+		 * @brief	Creates an empty, uninitialized managed instance of the resource interop object.
+		 */
+		static MonoObject* createInstance();
+
 		/************************************************************************/
 		/* 								CLR HOOKS						   		*/
 		/************************************************************************/

+ 5 - 0
SBansheeEngine/Include/BsScriptTextureCube.h

@@ -20,6 +20,11 @@ namespace BansheeEngine
 
 		ScriptTextureCube(MonoObject* instance, const HTexture& texture);
 
+		/**
+		 * @brief	Creates an empty, uninitialized managed instance of the resource interop object.
+		 */
+		static MonoObject* createInstance();
+
 		/************************************************************************/
 		/* 								CLR HOOKS						   		*/
 		/************************************************************************/

+ 5 - 0
SBansheeEngine/Source/BsScriptFont.cpp

@@ -38,6 +38,11 @@ namespace BansheeEngine
 		return font->getClosestSize(size);
 	}
 
+	MonoObject* ScriptFont::createInstance()
+	{
+		return metaData.scriptClass->createInstance();
+	}
+
 	ScriptCharRange::ScriptCharRange(MonoObject* instance)
 		:ScriptObject(instance)
 	{ }

+ 10 - 0
SBansheeEngine/Source/BsScriptGUISkin.cpp

@@ -84,4 +84,14 @@ namespace BansheeEngine
 
 		return output.getInternal();
 	}
+
+	MonoObject* ScriptGUISkin::createInstance()
+	{
+		bool dummy = false;
+
+		void* params[1];
+		params[0] = &dummy;
+
+		return metaData.scriptClass->createInstance("bool", params);
+	}
 }

+ 9 - 2
SBansheeEngine/Source/BsScriptManagedResource.cpp

@@ -15,7 +15,7 @@ namespace BansheeEngine
 	ScriptManagedResource::ScriptManagedResource(MonoObject* instance, const HManagedResource& resource)
 		:ScriptObject(instance), mResource(resource)
 	{
-		assert(instance != nullptr);
+		BS_ASSERT(instance != nullptr);
 
 		MonoUtil::getClassName(instance, mNamespace, mType);
 	}
@@ -74,7 +74,7 @@ namespace BansheeEngine
 			// instance which is only freed on unload().
 			// Note: During domain unload this could get called even if not all instances are released, but ManagedResourceManager
 			// should make sure all instances are unloaded before that happens.
-			assert(mResource == nullptr || !mResource.isLoaded());
+			BS_ASSERT(mResource == nullptr || !mResource.isLoaded());
 
 			ScriptResourceManager::instance().destroyScriptResource(this);
 		}
@@ -84,4 +84,11 @@ namespace BansheeEngine
 	{
 		mResource = static_resource_cast<ManagedResource>(resource);
 	}
+
+	MonoObject* ScriptManagedResource::createInstance()
+	{
+		// Implementation of this method is only relevant for native resources, this is just here to stop compiler from complaining
+		BS_ASSERT(false);
+		return nullptr;
+	}
 }

+ 10 - 0
SBansheeEngine/Source/BsScriptMaterial.cpp

@@ -275,4 +275,14 @@ namespace BansheeEngine
 
 		return scriptTexture->getManagedInstance();
 	}
+
+	MonoObject* ScriptMaterial::createInstance()
+	{
+		bool dummy = false;
+
+		void* params[1];
+		params[0] = &dummy;
+
+		return metaData.scriptClass->createInstance("bool", params);
+	}
 }

+ 5 - 0
SBansheeEngine/Source/BsScriptMesh.cpp

@@ -133,6 +133,11 @@ namespace BansheeEngine
 		}
 	}
 
+	MonoObject* ScriptMesh::createInstance()
+	{
+		return metaData.scriptClass->createInstance();
+	}
+
 	DrawOperationType ScriptMesh::meshTopologyToDrawOp(MeshTopology topology)
 	{
 		switch (topology)

+ 5 - 0
SBansheeEngine/Source/BsScriptPlainText.cpp

@@ -46,4 +46,9 @@ namespace BansheeEngine
 
 		plainText->setString(MonoUtil::monoToWString(text));
 	}
+
+	MonoObject* ScriptPlainText::createInstance()
+	{
+		return metaData.scriptClass->createInstance();
+	}
 }

+ 5 - 0
SBansheeEngine/Source/BsScriptPrefab.cpp

@@ -39,4 +39,9 @@ namespace BansheeEngine
 
 		return scriptInstance->getManagedInstance();
 	}
+
+	MonoObject* ScriptPrefab::createInstance()
+	{
+		return metaData.scriptClass->createInstance();
+	}
 }

+ 1 - 1
SBansheeEngine/Source/BsScriptResourceManager.cpp

@@ -38,7 +38,7 @@ namespace BansheeEngine
 	void ScriptResourceManager::createScriptResource(const ResourceHandle<InType>& resourceHandle, RetType** out)
 	{
 		MonoClass* resourceClass = RetType::getMetaData()->scriptClass;
-		MonoObject* monoInstance = resourceClass->createInstance();
+		MonoObject* monoInstance = RetType::createInstance();
 
 		createScriptResource(monoInstance, resourceHandle, out);
 	}

+ 5 - 0
SBansheeEngine/Source/BsScriptScriptCode.cpp

@@ -104,6 +104,11 @@ namespace BansheeEngine
 		return output;
 	}
 
+	MonoObject* ScriptScriptCode::createInstance()
+	{
+		return metaData.scriptClass->createInstance();
+	}
+
 	Vector<ScriptScriptCode::FullTypeName> ScriptScriptCode::parseTypes(const WString& code)
 	{
 		struct NamespaceData

+ 5 - 0
SBansheeEngine/Source/BsScriptShader.cpp

@@ -146,4 +146,9 @@ namespace BansheeEngine
 		*outTypes = types.getInternal();
 		*outVisibility = visibility.getInternal();
 	}
+
+	MonoObject* ScriptShader::createInstance()
+	{
+		return metaData.scriptClass->createInstance();
+	}
 }

+ 5 - 0
SBansheeEngine/Source/BsScriptShaderInclude.cpp

@@ -13,4 +13,9 @@ namespace BansheeEngine
 	{
 
 	}
+
+	MonoObject* ScriptShaderInclude::createInstance()
+	{
+		return metaData.scriptClass->createInstance();
+	}
 }

+ 5 - 0
SBansheeEngine/Source/BsScriptSpriteTexture.cpp

@@ -144,4 +144,9 @@ namespace BansheeEngine
 
 		return spriteTexture->getHeight();
 	}
+
+	MonoObject* ScriptSpriteTexture::createInstance()
+	{
+		return metaData.scriptClass->createInstance();
+	}
 }

+ 10 - 0
SBansheeEngine/Source/BsScriptStringTable.cpp

@@ -103,4 +103,14 @@ namespace BansheeEngine
 
 		*value = MonoUtil::wstringToMono(MonoManager::instance().getDomain(), nativeValue);
 	}
+
+	MonoObject* ScriptStringTable::createInstance()
+	{
+		bool dummy = false;
+
+		void* params[1];
+		params[0] = &dummy;
+
+		return metaData.scriptClass->createInstance("bool", params);
+	}
 }

+ 5 - 0
SBansheeEngine/Source/BsScriptTexture2D.cpp

@@ -101,4 +101,9 @@ namespace BansheeEngine
 		UINT32 subresourceIdx = texture->getProperties().mapToSubresourceIdx(0, mipLevel);
 		texture->writeSubresource(gCoreAccessor(), subresourceIdx, pixelData, false);
 	}
+
+	MonoObject* ScriptTexture2D::createInstance()
+	{
+		return metaData.scriptClass->createInstance();
+	}
 }

+ 5 - 0
SBansheeEngine/Source/BsScriptTexture3D.cpp

@@ -84,4 +84,9 @@ namespace BansheeEngine
 			texture->writeSubresource(gCoreAccessor(), subresourceIdx, scriptPixelData->getInternalValue(), false);
 		}
 	}
+
+	MonoObject* ScriptTexture3D::createInstance()
+	{
+		return metaData.scriptClass->createInstance();
+	}
 }

+ 5 - 0
SBansheeEngine/Source/BsScriptTextureCube.cpp

@@ -83,4 +83,9 @@ namespace BansheeEngine
 			texture->writeSubresource(gCoreAccessor(), subresourceIdx, scriptPixelData->getInternalValue(), false);
 		}
 	}
+
+	MonoObject* ScriptTextureCube::createInstance()
+	{
+		return metaData.scriptClass->createInstance();
+	}
 }