Просмотр исходного кода

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 10 лет назад
Родитель
Сommit
1b0786cf45
37 измененных файлов с 205 добавлено и 26 удалено
  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();
+	}
 }