From b9f11298e81dc10d4ee96ac54c1828607d55ca50 Mon Sep 17 00:00:00 2001 From: Ari Vuollet Date: Sun, 11 Dec 2022 13:54:12 +0200 Subject: [PATCH] Avoid pre-allocating custom attributes for managed types --- Source/Engine/Engine/NativeInterop.cs | 12 ++++++++++ Source/Engine/Scripting/DotNet/CoreCLR.h | 6 +++++ Source/Engine/Scripting/DotNet/MonoApi.cpp | 24 +++++++++++++++++++ Source/Engine/Scripting/ManagedCLR/MClass.cpp | 19 +++++++++++---- 4 files changed, 57 insertions(+), 4 deletions(-) diff --git a/Source/Engine/Engine/NativeInterop.cs b/Source/Engine/Engine/NativeInterop.cs index 6d1846512..841113c9b 100644 --- a/Source/Engine/Engine/NativeInterop.cs +++ b/Source/Engine/Engine/NativeInterop.cs @@ -1365,6 +1365,18 @@ namespace FlaxEngine *classAttributesCount = attributeTypes.Length; } + [UnmanagedCallersOnly] + internal static IntPtr GetCustomAttribute(IntPtr typeHandle, IntPtr attribHandle) + { + Type type = (Type)GCHandle.FromIntPtr(typeHandle).Target; + Type attribType = (Type)GCHandle.FromIntPtr(attribHandle).Target; + object attrib = type.GetCustomAttributes(false).FirstOrDefault(x => x.GetType() == attribType); + + if (attrib != null) + return GCHandle.ToIntPtr(GCHandle.Alloc(attrib, GCHandleType.Weak)); + return IntPtr.Zero; + } + [UnmanagedCallersOnly] internal static void GetClassInterfaces(IntPtr typeHandle, IntPtr* classInterfaces, int* classInterfacesCount) { diff --git a/Source/Engine/Scripting/DotNet/CoreCLR.h b/Source/Engine/Scripting/DotNet/CoreCLR.h index 2f9c2a753..d869beadc 100644 --- a/Source/Engine/Scripting/DotNet/CoreCLR.h +++ b/Source/Engine/Scripting/DotNet/CoreCLR.h @@ -4,6 +4,7 @@ #include #include "Engine/Core/Types/String.h" +#include "Engine/Core/Collections/Array.h" #include "Engine/Scripting/Types.h" #if defined(_WIN32) @@ -46,4 +47,9 @@ public: static gchandle NewGCHandleWeakref(void* obj, bool track_resurrection); static void* GetGCHandleTarget(const gchandle& gchandle); static void FreeGCHandle(const gchandle& gchandle); + + static bool HasCustomAttribute(void* klass, void* attribClass); + static bool HasCustomAttribute(void* klass); + static void* GetCustomAttribute(void* klass, void* attribClass); + static Array GetCustomAttributes(void* klass); }; diff --git a/Source/Engine/Scripting/DotNet/MonoApi.cpp b/Source/Engine/Scripting/DotNet/MonoApi.cpp index 2d290b65e..8409bd72a 100644 --- a/Source/Engine/Scripting/DotNet/MonoApi.cpp +++ b/Source/Engine/Scripting/DotNet/MonoApi.cpp @@ -587,6 +587,30 @@ const char* CoreCLR::GetClassFullname(void* klass) return ((CoreCLRClass*)klass)->GetFullname().Get(); } +bool CoreCLR::HasCustomAttribute(void* klass, void* attribClass) +{ + return CoreCLR::GetCustomAttribute(klass, attribClass) != nullptr; +} +bool CoreCLR::HasCustomAttribute(void* klass) +{ + return CoreCLR::GetCustomAttribute(klass, nullptr) != nullptr; +} +void* CoreCLR::GetCustomAttribute(void* klass, void* attribClass) +{ + return CoreCLR::CallStaticMethodInternal(TEXT("GetCustomAttribute"), ((CoreCLRClass*)klass)->GetTypeHandle(), ((CoreCLRClass*)attribClass)->GetTypeHandle()); +} +Array CoreCLR::GetCustomAttributes(void* klass) +{ + Array attrib = ((CoreCLRClass*)klass)->GetCustomAttributes(); + + Array attributes; + attributes.Resize(attrib.Count(), false); + for (int i = 0; i < attrib.Count(); i++) + attributes.Add(attrib[i]->GetHandle()); + + return attributes; +} + /* * loader.h */ diff --git a/Source/Engine/Scripting/ManagedCLR/MClass.cpp b/Source/Engine/Scripting/ManagedCLR/MClass.cpp index 53fe1b358..9475e78d6 100644 --- a/Source/Engine/Scripting/ManagedCLR/MClass.cpp +++ b/Source/Engine/Scripting/ManagedCLR/MClass.cpp @@ -14,6 +14,9 @@ #include #define GET_CUSTOM_ATTR() (MonoCustomAttrInfo*)(_attrInfo ? _attrInfo : _attrInfo = mono_custom_attrs_from_class(_monoClass)) #endif +#if USE_NETCORE +#include "Engine/Scripting/DotNet/CoreCLR.h" +#endif #if USE_MONO MClass::MClass(const MAssembly* parentAssembly, MonoClass* monoClass, const MString& fullname) @@ -375,7 +378,9 @@ MObject* MClass::CreateInstance(void** params, uint32 numParams) bool MClass::HasAttribute(const MClass* monoClass) const { -#if USE_MONO +#if USE_NETCORE + return CoreCLR::HasCustomAttribute(_monoClass, monoClass->GetNative()); +#elif USE_MONO MonoCustomAttrInfo* attrInfo = GET_CUSTOM_ATTR(); return attrInfo != nullptr && mono_custom_attrs_has_attr(attrInfo, monoClass->GetNative()) != 0; #else @@ -385,7 +390,9 @@ bool MClass::HasAttribute(const MClass* monoClass) const bool MClass::HasAttribute() const { -#if USE_MONO +#if USE_NETCORE + return CoreCLR::HasCustomAttribute(_monoClass); +#elif USE_MONO MonoCustomAttrInfo* attrInfo = GET_CUSTOM_ATTR(); return attrInfo && attrInfo->num_attrs > 0; #else @@ -395,7 +402,9 @@ bool MClass::HasAttribute() const MObject* MClass::GetAttribute(const MClass* monoClass) const { -#if USE_MONO +#if USE_NETCORE + return (MObject*)CoreCLR::GetCustomAttribute(_monoClass, monoClass->GetNative()); +#elif USE_MONO MonoCustomAttrInfo* attrInfo = GET_CUSTOM_ATTR(); return attrInfo ? mono_custom_attrs_get_attr(attrInfo, monoClass->GetNative()) : nullptr; #else @@ -409,7 +418,9 @@ const Array& MClass::GetAttributes() return _attributes; _hasCachedAttributes = true; -#if USE_MONO +#if USE_NETCORE + _attributes = *(Array*)(&CoreCLR::GetCustomAttributes(_monoClass)); +#elif USE_MONO MonoCustomAttrInfo* attrInfo = GET_CUSTOM_ATTR(); if (attrInfo == nullptr) return _attributes;