diff --git a/Source/Engine/Engine/NativeInterop.Unmanaged.cs b/Source/Engine/Engine/NativeInterop.Unmanaged.cs index 7e2755603..08eac6954 100644 --- a/Source/Engine/Engine/NativeInterop.Unmanaged.cs +++ b/Source/Engine/Engine/NativeInterop.Unmanaged.cs @@ -770,12 +770,20 @@ namespace FlaxEngine.Interop } [UnmanagedCallersOnly] - internal static void SetArrayValueReference(ManagedHandle arrayHandle, IntPtr valueHandle, int index) + internal static void WriteArrayReference(ManagedHandle arrayHandle, IntPtr valueHandle, int index) { ManagedArray managedArray = Unsafe.As(arrayHandle.Target); managedArray.ToSpan()[index] = valueHandle; } + [UnmanagedCallersOnly] + internal static void WriteArrayReferences(ManagedHandle arrayHandle, IntPtr spanPtr, int spanLength) + { + ManagedArray managedArray = Unsafe.As(arrayHandle.Target); + var unmanagedSpan = new Span(spanPtr.ToPointer(), spanLength); + unmanagedSpan.CopyTo(managedArray.ToSpan()); + } + [UnmanagedCallersOnly] internal static ManagedHandle LoadAssemblyImage(IntPtr assemblyPathPtr, IntPtr* assemblyName, IntPtr* assemblyFullName) { diff --git a/Source/Engine/Scripting/ManagedCLR/MCore.h b/Source/Engine/Scripting/ManagedCLR/MCore.h index 497c27657..e27682c52 100644 --- a/Source/Engine/Scripting/ManagedCLR/MCore.h +++ b/Source/Engine/Scripting/ManagedCLR/MCore.h @@ -110,6 +110,7 @@ public: static void WriteRef(void* ptr, MObject* ref); static void WriteValue(void* dst, void* src, int32 count, const MClass* klass); static void WriteArrayRef(MArray* dst, MObject* ref, int32 index); + static void WriteArrayRef(MArray* dst, Span span); #if USE_NETCORE static void* AllocateMemory(int32 size, bool coTaskMem = false); static void FreeMemory(void* ptr, bool coTaskMem = false); diff --git a/Source/Engine/Scripting/ManagedCLR/MUtils.h b/Source/Engine/Scripting/ManagedCLR/MUtils.h index 8e7b65a60..90bfa5327 100644 --- a/Source/Engine/Scripting/ManagedCLR/MUtils.h +++ b/Source/Engine/Scripting/ManagedCLR/MUtils.h @@ -104,8 +104,14 @@ struct MConverter void ToManagedArray(MArray* result, const Span& data) { + if (data.Length() == 0) + return; + + Array objects; + objects.Resize(data.Length(), false); for (int32 i = 0; i < data.Length(); i++) - MCore::GC::WriteArrayRef(result, (MObject*)MUtils::ToString(data[i]), i); + objects[i] = (MObject*)MUtils::ToString(data[i]); + MCore::GC::WriteArrayRef(result, Span(objects.Get(), objects.Count())); } void ToNativeArray(Span& result, const MArray* data) @@ -132,8 +138,14 @@ struct MConverter void ToManagedArray(MArray* result, const Span& data) { + if (data.Length() == 0) + return; + + Array objects; + objects.Resize(data.Length(), false); for (int32 i = 0; i < data.Length(); i++) - MCore::GC::WriteArrayRef(result, (MObject*)MUtils::ToString(data[i]), i); + objects[i] = (MObject*)MUtils::ToString(data[i]); + MCore::GC::WriteArrayRef(result, Span(objects.Get(), objects.Count())); } void ToNativeArray(Span& result, const MArray* data) @@ -160,8 +172,14 @@ struct MConverter void ToManagedArray(MArray* result, const Span& data) { + if (data.Length() == 0) + return; + + Array objects; + objects.Resize(data.Length(), false); for (int32 i = 0; i < data.Length(); i++) - MCore::GC::WriteArrayRef(result, (MObject*)MUtils::ToString(data[i]), i); + objects[i] = (MObject*)MUtils::ToString(data[i]); + MCore::GC::WriteArrayRef(result, Span(objects.Get(), objects.Count())); } void ToNativeArray(Span& result, const MArray* data) @@ -188,8 +206,14 @@ struct MConverter void ToManagedArray(MArray* result, const Span& data) { + if (data.Length() == 0) + return; + + Array objects; + objects.Resize(data.Length(), false); for (int32 i = 0; i < data.Length(); i++) - MCore::GC::WriteArrayRef(result, MUtils::BoxVariant(data[i]), i); + objects[i] = MUtils::BoxVariant(data[i]); + MCore::GC::WriteArrayRef(result, Span(objects.Get(), objects.Count())); } void ToNativeArray(Span& result, const MArray* data) @@ -216,8 +240,14 @@ struct MConverter::Va void ToManagedArray(MArray* result, const Span& data) { + if (data.Length() == 0) + return; + + Array objects; + objects.Resize(data.Length(), false); for (int32 i = 0; i < data.Length(); i++) - MCore::GC::WriteArrayRef(result, data[i] ? data[i]->GetOrCreateManagedInstance() : nullptr, i); + objects[i] = data[i] ? data[i]->GetOrCreateManagedInstance() : nullptr; + MCore::GC::WriteArrayRef(result, Span(objects.Get(), objects.Count())); } void ToNativeArray(Span& result, const MArray* data) @@ -239,8 +269,14 @@ struct MConverter::Val void ToManagedArray(MArray* result, const Span& data) { + if (data.Length() == 0) + return; + + Array objects; + objects.Resize(data.Length(), false); for (int32 i = 0; i < data.Length(); i++) - MCore::GC::WriteArrayRef(result, data[i].GetOrCreateManagedInstance(), i); + objects[i] = data[i].GetOrCreateManagedInstance(); + MCore::GC::WriteArrayRef(result, Span(objects.Get(), objects.Count())); } }; @@ -263,8 +299,16 @@ struct MConverter> void ToManagedArray(MArray* result, const Span>& data) { + if (data.Length() == 0) + return; + + Array objects; + objects.Resize(data.Length(), false); for (int32 i = 0; i < data.Length(); i++) - MCore::GC::WriteArrayRef(result, data[i].GetManagedInstance(), i); + objects[i] = data[i].GetManagedInstance(); + MCore::GC::WriteArrayRef(result, Span(objects.Get(), objects.Count())); + //for (int32 i = 0; i < data.Length(); i++) + // MCore::GC::WriteArrayRef(result, data[i].GetManagedInstance(), i); } void ToNativeArray(Span>& result, const MArray* data) @@ -294,8 +338,14 @@ struct MConverter> void ToManagedArray(MArray* result, const Span>& data) { + if (data.Length() == 0) + return; + + Array objects; + objects.Resize(data.Length(), false); for (int32 i = 0; i < data.Length(); i++) - MCore::GC::WriteArrayRef(result, data[i].GetManagedInstance(), i); + objects[i] = data[i].GetManagedInstance(); + MCore::GC::WriteArrayRef(result, Span(objects.Get(), objects.Count())); } void ToNativeArray(Span>& result, const MArray* data) diff --git a/Source/Engine/Scripting/Runtime/DotNet.cpp b/Source/Engine/Scripting/Runtime/DotNet.cpp index 07d9ea92a..784541d56 100644 --- a/Source/Engine/Scripting/Runtime/DotNet.cpp +++ b/Source/Engine/Scripting/Runtime/DotNet.cpp @@ -450,8 +450,14 @@ void MCore::GC::WriteValue(void* dst, void* src, int32 count, const MClass* klas void MCore::GC::WriteArrayRef(MArray* dst, MObject* ref, int32 index) { - static void* SetArrayValueReferencePtr = GetStaticMethodPointer(TEXT("SetArrayValueReference")); - CallStaticMethod(SetArrayValueReferencePtr, dst, ref, index); + static void* WriteArrayReferencePtr = GetStaticMethodPointer(TEXT("WriteArrayReference")); + CallStaticMethod(WriteArrayReferencePtr, dst, ref, index); +} + +void MCore::GC::WriteArrayRef(MArray* dst, Span refs) +{ + static void* WriteArrayReferencesPtr = GetStaticMethodPointer(TEXT("WriteArrayReferences")); + CallStaticMethod(WriteArrayReferencesPtr, dst, refs.Get(), refs.Length()); } void* MCore::GC::AllocateMemory(int32 size, bool coTaskMem) diff --git a/Source/Engine/Scripting/Runtime/Mono.cpp b/Source/Engine/Scripting/Runtime/Mono.cpp index 3ebb92ccc..5cd9e7f5f 100644 --- a/Source/Engine/Scripting/Runtime/Mono.cpp +++ b/Source/Engine/Scripting/Runtime/Mono.cpp @@ -857,6 +857,13 @@ void MCore::GC::WriteArrayRef(MArray* dst, MObject* ref, int32 index) mono_gc_wbarrier_set_arrayref(dst, (byte*)ptr + index * sizeof(void*), ref); } +void MCore::GC::WriteArrayRef(MArray* dst, Span refs) +{ + void* ptr = mono_array_addr_with_size(dst, 0, 0); + for (int32 index = 0; index < refs.Length(); index++) + mono_gc_wbarrier_set_arrayref(dst, (byte*)ptr + index * sizeof(void*), refs[index]); +} + void MCore::Thread::Attach() { if (!IsInMainThread() && !mono_domain_get()) diff --git a/Source/Engine/Scripting/Runtime/None.cpp b/Source/Engine/Scripting/Runtime/None.cpp index c9e51f8ea..73ee319e5 100644 --- a/Source/Engine/Scripting/Runtime/None.cpp +++ b/Source/Engine/Scripting/Runtime/None.cpp @@ -176,6 +176,10 @@ void MCore::GC::WriteArrayRef(MArray* dst, MObject* ref, int32 index) { } +void MCore::GC::WriteArrayRef(MArray* dst, Span refs) +{ +} + void MCore::Thread::Attach() { }