Merge branch 'master' into 1.1
This commit is contained in:
13
Development/Documentation/mono.md
Normal file
13
Development/Documentation/mono.md
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
## Mono
|
||||||
|
|
||||||
|
Custom fork: [https://github.com/FlaxEngine/mono](https://github.com/FlaxEngine/mono) with custom features for C# assemblies hot-reloading at runtime without domain unload (more: [https://flaxengine.com/blog/flax-facts-16-scripts-hot-reload/](https://flaxengine.com/blog/flax-facts-16-scripts-hot-reload/)).
|
||||||
|
|
||||||
|
### Notes
|
||||||
|
|
||||||
|
Some useful notes and tips for devs:
|
||||||
|
* When working with mono fork set `localRepoPath` to local repo location in `Source\Tools\Flax.Build\Deps\Dependencies\mono.cs`
|
||||||
|
* To update mono deps when developing/updating use `.\Development\Scripts\Windows\CallBuildTool.bat -log -ReBuildDeps -verbose -depsToBuild=mono -platform=Windows`, then build engine and run it
|
||||||
|
* `MONO_GC_DEBUG=check-remset-consistency` - it will do additional checks at each collection to see if there are any missing write barriers
|
||||||
|
* `MONO_GC_DEBUG=nursery-canaries` - it might catch some buffer overflows in case of problems in code.
|
||||||
|
* Methods `mono_custom_attrs_from_property` and `mono_custom_attrs_get_attr` are internally cached
|
||||||
|
* If C++ mono call a method in c# that will throw an error, error will be handled but, not completly. Calling relase domain will return random `Access memory violation`. First search for error in c# code. No workaround yet.
|
||||||
@@ -269,6 +269,8 @@ public:
|
|||||||
{
|
{
|
||||||
return String(_data.Get(), _data.Count());
|
return String(_data.Get(), _data.Count());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StringView ToStringView() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline uint32 GetHash(const StringBuilder& key)
|
inline uint32 GetHash(const StringBuilder& key)
|
||||||
|
|||||||
@@ -2,6 +2,12 @@
|
|||||||
|
|
||||||
#include "StringView.h"
|
#include "StringView.h"
|
||||||
#include "String.h"
|
#include "String.h"
|
||||||
|
#include "StringBuilder.h"
|
||||||
|
|
||||||
|
StringView StringBuilder::ToStringView() const
|
||||||
|
{
|
||||||
|
return StringView(_data.Get(), _data.Count());
|
||||||
|
}
|
||||||
|
|
||||||
StringView StringView::Empty;
|
StringView StringView::Empty;
|
||||||
|
|
||||||
|
|||||||
@@ -118,6 +118,8 @@ void* MonoCalloc(size_t count, size_t size)
|
|||||||
|
|
||||||
#if USE_MONO_PROFILER
|
#if USE_MONO_PROFILER
|
||||||
|
|
||||||
|
#include "Engine/Core/Types/StringBuilder.h"
|
||||||
|
|
||||||
struct FlaxMonoProfiler
|
struct FlaxMonoProfiler
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
@@ -126,7 +128,7 @@ FlaxMonoProfiler Profiler;
|
|||||||
|
|
||||||
struct StackWalkDataResult
|
struct StackWalkDataResult
|
||||||
{
|
{
|
||||||
StringAnsi Buffer;
|
StringBuilder Buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
mono_bool OnStackWalk(MonoMethod* method, int32_t native_offset, int32_t il_offset, mono_bool managed, void* data)
|
mono_bool OnStackWalk(MonoMethod* method, int32_t native_offset, int32_t il_offset, mono_bool managed, void* data)
|
||||||
@@ -138,16 +140,16 @@ mono_bool OnStackWalk(MonoMethod* method, int32_t native_offset, int32_t il_offs
|
|||||||
auto mName = mono_method_get_name(method);
|
auto mName = mono_method_get_name(method);
|
||||||
auto mKlassNameSpace = mono_class_get_namespace(mono_method_get_class(method));
|
auto mKlassNameSpace = mono_class_get_namespace(mono_method_get_class(method));
|
||||||
auto mKlassName = mono_class_get_name(mono_method_get_class(method));
|
auto mKlassName = mono_class_get_name(mono_method_get_class(method));
|
||||||
result->Buffer += mKlassNameSpace;
|
result->Buffer.Append(mKlassNameSpace);
|
||||||
result->Buffer += ".";
|
result->Buffer.Append(TEXT("."));
|
||||||
result->Buffer += mKlassName;
|
result->Buffer.Append(mKlassName);
|
||||||
result->Buffer += "::";
|
result->Buffer.Append(TEXT("::"));
|
||||||
result->Buffer += mName;
|
result->Buffer.Append(mName);
|
||||||
result->Buffer += "\n";
|
result->Buffer.Append(TEXT("\n"));
|
||||||
}
|
}
|
||||||
else if (!managed)
|
else if (!managed)
|
||||||
{
|
{
|
||||||
result->Buffer += "<unmanaged>\n";
|
result->Buffer.Append(TEXT("<unmanaged>\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -170,10 +172,10 @@ void OnGCAllocation(MonoProfiler* profiler, MonoObject* obj)
|
|||||||
if (details)
|
if (details)
|
||||||
{
|
{
|
||||||
StackWalkDataResult stackTrace;
|
StackWalkDataResult stackTrace;
|
||||||
stackTrace.Buffer.reserve(1024);
|
stackTrace.Buffer.SetCapacity(1024);
|
||||||
mono_stack_walk(&OnStackWalk, &stackTrace);
|
mono_stack_walk(&OnStackWalk, &stackTrace);
|
||||||
|
|
||||||
LOG(Info, "GC new: {0}.{1} ({2} bytes). Stack Trace:\n{3}", name_space, name, size, stackTrace.Buffer.c_str());
|
LOG(Info, "GC new: {0}.{1} ({2} bytes). Stack Trace:\n{3}", String(name_space), String(name), size, stackTrace.Buffer.ToStringView());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -12,8 +12,9 @@ namespace Flax.Build.Bindings
|
|||||||
partial class BindingsGenerator
|
partial class BindingsGenerator
|
||||||
{
|
{
|
||||||
private static readonly bool[] CppParamsThatNeedLocalVariable = new bool[64];
|
private static readonly bool[] CppParamsThatNeedLocalVariable = new bool[64];
|
||||||
private static readonly bool[] CppParamsThatNeedConvertion = new bool[64];
|
private static readonly bool[] CppParamsThatNeedConversion = new bool[64];
|
||||||
private static readonly string[] CppParamsThatNeedConvertionWrappers = new string[64];
|
private static readonly string[] CppParamsThatNeedConversionWrappers = new string[64];
|
||||||
|
private static readonly string[] CppParamsThatNeedConversionTypes = new string[64];
|
||||||
private static readonly string[] CppParamsWrappersCache = new string[64];
|
private static readonly string[] CppParamsWrappersCache = new string[64];
|
||||||
public static readonly List<ApiTypeInfo> CppUsedNonPodTypes = new List<ApiTypeInfo>();
|
public static readonly List<ApiTypeInfo> CppUsedNonPodTypes = new List<ApiTypeInfo>();
|
||||||
private static readonly List<ApiTypeInfo> CppUsedNonPodTypesList = new List<ApiTypeInfo>();
|
private static readonly List<ApiTypeInfo> CppUsedNonPodTypesList = new List<ApiTypeInfo>();
|
||||||
@@ -620,7 +621,7 @@ namespace Flax.Build.Bindings
|
|||||||
contents.Append(", ");
|
contents.Append(", ");
|
||||||
separator = true;
|
separator = true;
|
||||||
|
|
||||||
CppParamsThatNeedConvertion[i] = false;
|
CppParamsThatNeedConversion[i] = false;
|
||||||
CppParamsWrappersCache[i] = GenerateCppWrapperManagedToNative(buildData, parameterInfo.Type, caller, out var managedType, functionInfo, out CppParamsThatNeedLocalVariable[i]);
|
CppParamsWrappersCache[i] = GenerateCppWrapperManagedToNative(buildData, parameterInfo.Type, caller, out var managedType, functionInfo, out CppParamsThatNeedLocalVariable[i]);
|
||||||
contents.Append(managedType);
|
contents.Append(managedType);
|
||||||
if (parameterInfo.IsRef || parameterInfo.IsOut || UsePassByReference(buildData, parameterInfo.Type, caller))
|
if (parameterInfo.IsRef || parameterInfo.IsOut || UsePassByReference(buildData, parameterInfo.Type, caller))
|
||||||
@@ -654,8 +655,8 @@ namespace Flax.Build.Bindings
|
|||||||
if (convertOutputParameter)
|
if (convertOutputParameter)
|
||||||
{
|
{
|
||||||
useInlinedReturn = false;
|
useInlinedReturn = false;
|
||||||
CppParamsThatNeedConvertion[i] = true;
|
CppParamsThatNeedConversion[i] = true;
|
||||||
CppParamsThatNeedConvertionWrappers[i] = GenerateCppWrapperNativeToManaged(buildData, parameterInfo.Type, caller, out _, functionInfo);
|
CppParamsThatNeedConversionWrappers[i] = GenerateCppWrapperNativeToManaged(buildData, parameterInfo.Type, caller, out CppParamsThatNeedConversionTypes[i], functionInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -717,7 +718,7 @@ namespace Flax.Build.Bindings
|
|||||||
callParams += ", ";
|
callParams += ", ";
|
||||||
separator = true;
|
separator = true;
|
||||||
var name = parameterInfo.Name;
|
var name = parameterInfo.Name;
|
||||||
if (CppParamsThatNeedConvertion[i] && (!FindApiTypeInfo(buildData, parameterInfo.Type, caller)?.IsStruct ?? false))
|
if (CppParamsThatNeedConversion[i] && (!FindApiTypeInfo(buildData, parameterInfo.Type, caller)?.IsStruct ?? false))
|
||||||
name = '*' + name;
|
name = '*' + name;
|
||||||
|
|
||||||
string param = string.Empty;
|
string param = string.Empty;
|
||||||
@@ -735,7 +736,7 @@ namespace Flax.Build.Bindings
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Special case for output result parameters that needs additional converting from native to managed format (such as non-POD structures or output array parameter)
|
// Special case for output result parameters that needs additional converting from native to managed format (such as non-POD structures or output array parameter)
|
||||||
if (CppParamsThatNeedConvertion[i])
|
if (CppParamsThatNeedConversion[i])
|
||||||
{
|
{
|
||||||
var apiType = FindApiTypeInfo(buildData, parameterInfo.Type, caller);
|
var apiType = FindApiTypeInfo(buildData, parameterInfo.Type, caller);
|
||||||
if (apiType != null)
|
if (apiType != null)
|
||||||
@@ -792,9 +793,41 @@ namespace Flax.Build.Bindings
|
|||||||
var parameterInfo = functionInfo.Parameters[i];
|
var parameterInfo = functionInfo.Parameters[i];
|
||||||
|
|
||||||
// Special case for output result parameters that needs additional converting from native to managed format (such as non-POD structures or output array parameter)
|
// Special case for output result parameters that needs additional converting from native to managed format (such as non-POD structures or output array parameter)
|
||||||
if (CppParamsThatNeedConvertion[i])
|
if (CppParamsThatNeedConversion[i])
|
||||||
{
|
{
|
||||||
contents.AppendFormat(" *{0} = {1};", parameterInfo.Name, string.Format(CppParamsThatNeedConvertionWrappers[i], parameterInfo.Name + "Temp")).AppendLine();
|
var value = string.Format(CppParamsThatNeedConversionWrappers[i], parameterInfo.Name + "Temp");
|
||||||
|
|
||||||
|
// MonoObject* parameters returned by reference need write barrier for GC
|
||||||
|
if (parameterInfo.IsOut)
|
||||||
|
{
|
||||||
|
var apiType = FindApiTypeInfo(buildData, parameterInfo.Type, caller);
|
||||||
|
if (apiType != null)
|
||||||
|
{
|
||||||
|
if (apiType.IsClass)
|
||||||
|
{
|
||||||
|
contents.AppendFormat(" mono_gc_wbarrier_generic_store({0}, (MonoObject*){1});", parameterInfo.Name, value).AppendLine();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (apiType.IsStruct && !apiType.IsPod)
|
||||||
|
{
|
||||||
|
CppIncludeFiles.Add("Engine/Scripting/ManagedCLR/MClass.h");
|
||||||
|
contents.AppendFormat(" {{ auto _temp = {1}; mono_gc_wbarrier_value_copy({0}, &_temp, 1, {2}::TypeInitializer.GetType().ManagedClass->GetNative()); }}", parameterInfo.Name, value, apiType.FullNameNative).AppendLine();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// BytesContainer
|
||||||
|
if (parameterInfo.Type.Type == "BytesContainer" && parameterInfo.Type.GenericArgs == null)
|
||||||
|
{
|
||||||
|
contents.AppendFormat(" mono_gc_wbarrier_generic_store({0}, (MonoObject*){1});", parameterInfo.Name, value).AppendLine();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Exception($"Unsupported type of parameter '{parameterInfo}' in method '{functionInfo}' to be passed using 'out'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
contents.AppendFormat(" *{0} = {1};", parameterInfo.Name, value).AppendLine();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user