From 2ceb8ba96cf93ef1db157e5e26df30565f928d5e Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 22 Apr 2025 18:53:26 +0200 Subject: [PATCH 01/14] Use assembly store for debug builds on CLR --- .../Xamarin.Android.Common.targets | 57 ++++++++++++++++--- src/native/clr/host/assembly-store.cc | 12 +++- 2 files changed, 60 insertions(+), 9 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index b48988a65e7..511945a4009 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -338,10 +338,21 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved. - - <_AndroidAotStripLibraries Condition=" '$(_AndroidAotStripLibraries)' == '' And '$(AndroidIncludeDebugSymbols)' != 'true' ">True + false true + <_AndroidUseAssemblyStore>$(AndroidUseAssemblyStore) + + + + + <_AndroidUseAssemblyStore Condition="'$(EmbedAssembliesIntoApk)' == 'true' ">true + <_AndroidUseAssemblyStore Condition="'$(EmbedAssembliesIntoApk)' != 'true' ">false + + + + <_AndroidAotStripLibraries Condition=" '$(_AndroidAotStripLibraries)' == '' And '$(AndroidIncludeDebugSymbols)' != 'true' ">True True False True @@ -1728,7 +1739,7 @@ because xbuild doesn't support framework reference assemblies. .so;$(AndroidStoreUncompressedFileExtensions) .dex;$(AndroidStoreUncompressedFileExtensions) - .blob;$(AndroidStoreUncompressedFileExtensions) + .blob;$(AndroidStoreUncompressedFileExtensions) @@ -1862,9 +1873,39 @@ because xbuild doesn't support framework reference assemblies. + ResolvedAssemblies="@(_ResolvedAssemblies)" + ResolvedUserAssemblies="@(_ResolvedUserAssemblies)" + SatelliteAssemblies="@(_AndroidResolvedSatellitePaths)" + IntermediateOutputDirectory="$(IntermediateOutputPath)" + NativeLibraries="@(AndroidNativeLibrary);@(EmbeddedNativeLibrary);@(FrameworkNativeLibrary)" + MonoComponents="@(_MonoComponent)" + MainAssembly="$(TargetPath)" + OutputDirectory="$(_AndroidIntermediateJavaSourceDirectory)mono" + EnvironmentOutputDirectory="$(IntermediateOutputPath)android" + TargetFrameworkVersion="$(TargetFrameworkVersion)" + Manifest="$(IntermediateOutputPath)android\AndroidManifest.xml" + Environments="@(_EnvironmentFiles)" + AndroidAotMode="$(AndroidAotMode)" + AndroidAotEnableLazyLoad="$(AndroidAotEnableLazyLoad)" + EnableLLVM="$(EnableLLVM)" + HttpClientHandlerType="$(AndroidHttpClientHandlerType)" + TlsProvider="$(AndroidTlsProvider)" + Debug="$(AndroidIncludeDebugSymbols)" + AndroidSequencePointsMode="$(_SequencePointsMode)" + EnableSGenConcurrent="$(AndroidEnableSGenConcurrent)" + SupportedAbis="@(_BuildTargetAbis)" + AndroidPackageName="$(_AndroidPackage)" + EnablePreloadAssembliesDefault="$(_AndroidEnablePreloadAssembliesDefault)" + PackageNamingPolicy="$(AndroidPackageNamingPolicy)" + BoundExceptionType="$(AndroidBoundExceptionType)" + RuntimeConfigBinFilePath="$(_BinaryRuntimeConfigPath)" + UseAssemblyStore="$(_AndroidUseAssemblyStore)" + EnableMarshalMethods="$(_AndroidUseMarshalMethods)" + EnableManagedMarshalMethodsLookup="$(_AndroidUseManagedMarshalMethodsLookup)" + CustomBundleConfigFile="$(AndroidBundleConfigurationFile)" + TargetsCLR="$(_AndroidUseCLR)" + ProjectRuntimeConfigFilePath="$(ProjectRuntimeConfigFilePath)" + > + UseAssemblyStore="$(_AndroidUseAssemblyStore)"> @@ -2313,7 +2354,7 @@ because xbuild doesn't support framework reference assemblies. IntermediateOutputPath="$(IntermediateOutputPath)" ResolvedAssemblies="@(_BuildApkAssembliesToAddToArchive)" SupportedAbis="@(_BuildTargetAbis)" - UseAssemblyStore="$(AndroidUseAssemblyStore)" + UseAssemblyStore="$(_AndroidUseAssemblyStore)" RuntimePackLibraryDirectories="@(_RuntimePackLibraryDirectory)"> diff --git a/src/native/clr/host/assembly-store.cc b/src/native/clr/host/assembly-store.cc index db5dfc94328..402584d09df 100644 --- a/src/native/clr/host/assembly-store.cc +++ b/src/native/clr/host/assembly-store.cc @@ -176,7 +176,17 @@ auto AssemblyStore::find_assembly_store_entry (hash_t hash, const AssemblyStoreI auto AssemblyStore::open_assembly (std::string_view const& name, int64_t &size) noexcept -> void* { hash_t name_hash = xxhash::hash (name.data (), name.length ()); - log_debug (LOG_ASSEMBLY, "assembly_store_open_from_bundles: looking for bundled name: '{}' (hash {:x})", optional_string (name.data ()), name_hash); + log_debug (LOG_ASSEMBLY, "AssemblyStore::open_assembly: looking for bundled name: '{}' (hash {:x})", optional_string (name.data ()), name_hash); + + if constexpr (Constants::is_debug_build) { + // TODO: implement filesystem lookup here + + // In fastdev mode we might not have any assembly store. + if (assembly_store_hashes == nullptr) { + log_warn (LOG_ASSEMBLY, "Assembly store not registered. Unable to look up assembly '{}'", name); + return nullptr; + } + } const AssemblyStoreIndexEntry *hash_entry = find_assembly_store_entry (name_hash, assembly_store_hashes, assembly_store.index_entry_count); if (hash_entry == nullptr) { From 056926749c0fcfa1eaf2dd79c45c4d7fd5c1a8e3 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 22 Apr 2025 18:53:52 +0200 Subject: [PATCH 02/14] Timing init fixlet + build deps --- src/native/common/runtime-base/timing-internal.cc | 10 ++++++---- src/native/native.targets | 2 ++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/native/common/runtime-base/timing-internal.cc b/src/native/common/runtime-base/timing-internal.cc index 30cc690821e..1c8cf1ce104 100644 --- a/src/native/common/runtime-base/timing-internal.cc +++ b/src/native/common/runtime-base/timing-internal.cc @@ -26,15 +26,17 @@ void FastTiming::really_initialize (bool log_immediately) noexcept open_sequences.push (0); open_sequences.pop (); + // Options in `debug.mono.timing` are relevant only when immediate logging is disabled + if (immediate_logging) { + log_warn (LOG_DEFAULT, " immediate mode, returning"); + return; + } + dynamic_local_property_string value; if (AndroidSystem::monodroid_get_system_property (Constants::DEBUG_MONO_TIMING, value) != 0) { internal_timing.parse_options (value); } - if (immediate_logging) { - return; - } - log_write ( LOG_TIMING, LogLevel::Info, diff --git a/src/native/native.targets b/src/native/native.targets index 10bb1f372f1..df70d1cab5f 100644 --- a/src/native/native.targets +++ b/src/native/native.targets @@ -38,6 +38,7 @@ <_ConfigureRuntimesInputs Include="common\libstub\CMakeLists.txt" /> <_ConfigureRuntimesInputs Include="common\libunwind\CMakeLists.txt" /> <_ConfigureRuntimesInputs Include="common\lz4\CMakeLists.txt" /> + <_ConfigureRuntimesInputs Include="common\runtime-base\CMakeLists.txt" /> <_ConfigureRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(FlavorIntermediateOutputPath)\%(AndroidRID)-Debug\CMakeCache.txt')" /> <_ConfigureRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(FlavorIntermediateOutputPath)\%(AndroidRID)-Release\CMakeCache.txt')" /> @@ -171,6 +172,7 @@ <_RuntimeSources Include="common\archive-dso-stub\*.cc" /> <_RuntimeSources Include="common\include\**\*.hh" /> <_RuntimeSources Include="common\libstub\*.cc;common\libstub\*.hh" /> + <_RuntimeSources Include="common\runtime-base\*.cc" /> <_RuntimeSources Include="$(LZ4SourceFullPath)\lib\lz4.c;$(LZ4SourceFullPath)\lib\lz4.h" /> From 0d6e87c02ea3140a0649d99764e4178a9e658387 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 22 Apr 2025 18:57:49 +0200 Subject: [PATCH 03/14] Don't need this --- src/native/common/runtime-base/timing-internal.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/src/native/common/runtime-base/timing-internal.cc b/src/native/common/runtime-base/timing-internal.cc index 1c8cf1ce104..ebf8d111893 100644 --- a/src/native/common/runtime-base/timing-internal.cc +++ b/src/native/common/runtime-base/timing-internal.cc @@ -28,7 +28,6 @@ void FastTiming::really_initialize (bool log_immediately) noexcept // Options in `debug.mono.timing` are relevant only when immediate logging is disabled if (immediate_logging) { - log_warn (LOG_DEFAULT, " immediate mode, returning"); return; } From 9301886462d63b4b8f68b107cc2a90e0efbcf36e Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 22 Apr 2025 22:01:40 +0200 Subject: [PATCH 04/14] Works. Sorta. Lookup is done in managed, because type name is passed without assembly name. Need to change format of the generated debug maps. --- src/native/clr/host/typemap.cc | 80 +++++++++++++++++++++++--- src/native/clr/include/host/typemap.hh | 11 +++- 2 files changed, 82 insertions(+), 9 deletions(-) diff --git a/src/native/clr/host/typemap.cc b/src/native/clr/host/typemap.cc index b2ce3bff8cd..605a14930e8 100644 --- a/src/native/clr/host/typemap.cc +++ b/src/native/clr/host/typemap.cc @@ -65,9 +65,44 @@ namespace { #if defined(DEBUG) [[gnu::always_inline]] -auto TypeMapper::typemap_managed_to_java_debug (const char *typeName, const uint8_t *mvid) noexcept -> const char* +auto TypeMapper::typemap_type_to_type_debug (const char *typeName, const TypeMapEntry *map, std::string_view const& from_name, std::string_view const& to_name) noexcept -> const char* { - Helpers::abort_application ("TypeMap support for Debug builds not implemented yet"sv); + auto equal = [](TypeMapEntry const& entry, const char *key) -> bool { + if (entry.from == nullptr) { + return 1; + } + + return strcmp (key, entry.from) == 0; + }; + + auto less_than = [](TypeMapEntry const& entry, const char *key) -> bool { + if (entry.from == nullptr) { + return 1; + } + + return strcmp (key, entry.from); + }; + + ssize_t idx = Search::binary_search (typeName, map, type_map.entry_count); + if (idx >= 0) [[likely]] { + log_debug ( + LOG_ASSEMBLY, + "{} type '{}' maps to {} type '{}'", + from_name, + optional_string (typeName), + to_name, + optional_string (type_map.managed_to_java[idx].to) + ); + return type_map.managed_to_java[idx].to; + } + + return nullptr; +} + +[[gnu::always_inline]] +auto TypeMapper::typemap_managed_to_java_debug (const char *typeName) noexcept -> const char* +{ + return typemap_type_to_type_debug (typeName, type_map.managed_to_java, MANAGED, JAVA); } #endif // def DEBUG @@ -208,8 +243,9 @@ auto TypeMapper::typemap_managed_to_java_release (const char *typeName, const ui #endif // def RELEASE [[gnu::flatten]] -auto TypeMapper::typemap_managed_to_java (const char *typeName, const uint8_t *mvid) noexcept -> const char* +auto TypeMapper::typemap_managed_to_java (const char *typeName, [[maybe_unused]] const uint8_t *mvid) noexcept -> const char* { + log_debug (LOG_ASSEMBLY, "typemap_managed_to_java: looking up type '{}'", optional_string (typeName)); if (FastTiming::enabled ()) [[unlikely]] { internal_timing.start_event (TimingEventKind::ManagedToJava); } @@ -223,7 +259,7 @@ auto TypeMapper::typemap_managed_to_java (const char *typeName, const uint8_t *m #if defined(RELEASE) ret = typemap_managed_to_java_release (typeName, mvid); #else - ret = typemap_managed_to_java_debug (typeName, mvid); + ret = typemap_managed_to_java_debug (typeName); #endif if (FastTiming::enabled ()) [[unlikely]] { @@ -235,9 +271,12 @@ auto TypeMapper::typemap_managed_to_java (const char *typeName, const uint8_t *m #if defined(DEBUG) [[gnu::flatten]] -auto TypeMapper::typemap_java_to_managed (const char *java_type_name, char const** assembly_name, uint32_t *managed_type_token_id) noexcept -> bool +auto TypeMapper::typemap_java_to_managed_debug (const char *java_type_name, char const** assembly_name, uint32_t *managed_type_token_id) noexcept -> bool { - Helpers::abort_application ("typemap_java_to_managed not implemented for debug builds yet"); + // FIXME: this is currently VERY broken + *assembly_name = nullptr; + *managed_type_token_id = 0; + return typemap_type_to_type_debug (java_type_name, type_map.java_to_managed, JAVA, MANAGED); } #else // def DEBUG @@ -253,7 +292,7 @@ auto TypeMapper::find_java_to_managed_entry (hash_t name_hash) noexcept -> const } [[gnu::flatten]] -auto TypeMapper::typemap_java_to_managed (const char *java_type_name, char const** assembly_name, uint32_t *managed_type_token_id) noexcept -> bool +auto TypeMapper::typemap_java_to_managed_release (const char *java_type_name, char const** assembly_name, uint32_t *managed_type_token_id) noexcept -> bool { if (FastTiming::enabled ()) [[unlikely]] { internal_timing.start_event (TimingEventKind::JavaToManaged); @@ -323,3 +362,30 @@ auto TypeMapper::typemap_java_to_managed (const char *java_type_name, char const return true; } #endif // ndef DEBUG + +[[gnu::flatten]] +auto TypeMapper::typemap_java_to_managed (const char *java_type_name, char const** assembly_name, uint32_t *managed_type_token_id) noexcept -> bool +{ + log_debug (LOG_ASSEMBLY, "typemap_java_to_managed: looking up type '{}'", optional_string (java_type_name)); + if (FastTiming::enabled ()) [[unlikely]] { + internal_timing.start_event (TimingEventKind::JavaToManaged); + } + + if (java_type_name == nullptr) [[unlikely]] { + log_warn (LOG_ASSEMBLY, "typemap: type name not specified in typemap_java_to_managed"); + return false; + } + + bool ret; +#if defined(RELEASE) + ret = typemap_java_to_managed_release (java_type_name, assembly_name, managed_type_token_id); +#else + ret = typemap_java_to_managed_debug (java_type_name, assembly_name, managed_type_token_id); +#endif + + if (FastTiming::enabled ()) [[unlikely]] { + internal_timing.end_event (); + } + + return ret; +} diff --git a/src/native/clr/include/host/typemap.hh b/src/native/clr/include/host/typemap.hh index f695f0ce5d4..79320555305 100644 --- a/src/native/clr/include/host/typemap.hh +++ b/src/native/clr/include/host/typemap.hh @@ -1,6 +1,7 @@ #pragma once #include +#include #include "../runtime-base/logger.hh" #include @@ -9,9 +10,12 @@ namespace xamarin::android { class TypeMapper { + static constexpr std::string_view MANAGED { "Managed" }; + static constexpr std::string_view JAVA { "Java" }; + public: static auto typemap_managed_to_java (const char *typeName, const uint8_t *mvid) noexcept -> const char*; - static auto typemap_java_to_managed (const char *java_type_name, char const** assembly_name, uint32_t *managed_type_doken_id) noexcept -> bool; + static auto typemap_java_to_managed (const char *java_type_name, char const** assembly_name, uint32_t *managed_type_token_id) noexcept -> bool; private: #if defined(RELEASE) @@ -19,10 +23,13 @@ namespace xamarin::android { static auto find_module_entry (const uint8_t *mvid, const TypeMapModule *entries, size_t entry_count) noexcept -> const TypeMapModule*; static auto find_managed_to_java_map_entry (hash_t name_hash, const TypeMapModuleEntry *map, size_t entry_count) noexcept -> const TypeMapModuleEntry*; static auto typemap_managed_to_java_release (const char *typeName, const uint8_t *mvid) noexcept -> const char*; + static auto typemap_java_to_managed_release (const char *java_type_name, char const** assembly_name, uint32_t *managed_type_token_id) noexcept -> bool; static auto find_java_to_managed_entry (hash_t name_hash) noexcept -> const TypeMapJava*; #else - static auto typemap_managed_to_java_debug (const char *typeName, const uint8_t *mvid) noexcept -> const char*; + static auto typemap_type_to_type_debug (const char *typeName, const TypeMapEntry *map, std::string_view const& from_name, std::string_view const& to_name) noexcept -> const char*; + static auto typemap_managed_to_java_debug (const char *typeName) noexcept -> const char*; + static auto typemap_java_to_managed_debug (const char *java_type_name, char const** assembly_name, uint32_t *managed_type_token_id) noexcept -> bool; #endif }; } From 6d110836938b509425db0b97876ec65c60b48acb Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 23 Apr 2025 18:25:37 +0200 Subject: [PATCH 05/14] New data structures LLVM IR generation --- .../Utilities/TypeMapCecilAdapter.cs | 32 ++- .../Utilities/TypeMapGenerator.cs | 30 ++- ...TypeMappingDebugNativeAssemblyGenerator.cs | 10 +- ...eMappingDebugNativeAssemblyGeneratorCLR.cs | 237 ++++++++++++++++++ src/native/clr/host/typemap.cc | 7 +- src/native/clr/include/host/typemap.hh | 2 +- src/native/clr/include/xamarin-app.hh | 17 +- .../xamarin-app-stub/application_dso_stub.cc | 10 +- 8 files changed, 318 insertions(+), 27 deletions(-) create mode 100644 src/Xamarin.Android.Build.Tasks/Utilities/TypeMappingDebugNativeAssemblyGeneratorCLR.cs diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/TypeMapCecilAdapter.cs b/src/Xamarin.Android.Build.Tasks/Utilities/TypeMapCecilAdapter.cs index 0273e253d5e..9aad6e4c2cc 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/TypeMapCecilAdapter.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/TypeMapCecilAdapter.cs @@ -7,13 +7,15 @@ using ReleaseGenerationState = Xamarin.Android.Tasks.TypeMapGenerator.ReleaseGenerationState; using TypeMapDebugEntry = Xamarin.Android.Tasks.TypeMapGenerator.TypeMapDebugEntry; using TypeMapReleaseEntry = Xamarin.Android.Tasks.TypeMapGenerator.TypeMapReleaseEntry; +using TypeMapDebugDataSets = Xamarin.Android.Tasks.TypeMapGenerator.TypeMapDebugDataSets; +using TypeMapDebugAssembly = Xamarin.Android.Tasks.TypeMapGenerator.TypeMapDebugAssembly; namespace Xamarin.Android.Tasks; // Converts types from Mono.Cecil to the format used by the typemap generator. class TypeMapCecilAdapter { - public static (List javaToManaged, List managedToJava) GetDebugNativeEntries (NativeCodeGenState state) + public static TypeMapDebugDataSets GetDebugNativeEntries (NativeCodeGenState state, bool needUniqueAssemblies) { var (javaToManaged, managedToJava, foundJniNativeRegistration) = GetDebugNativeEntries (state.AllJavaTypes, state.TypeCache); @@ -29,19 +31,41 @@ public static (List javaToManaged, List ma var managedToJava = new List (); var foundJniNativeRegistration = false; - foreach (var td in types) { - foundJniNativeRegistration = JniAddNativeMethodRegistrationAttributeFound (foundJniNativeRegistration, td); + var javaDuplicates = new Dictionary> (StringComparer.Ordinal); + var uniqueAssemblies = needUniqueAssemblies ? new Dictionary (StringComparer.OrdinalIgnoreCase) : null; + foreach (TypeDefinition td in state.AllJavaTypes) { + UpdateApplicationConfig (state, td); TypeMapDebugEntry entry = GetDebugEntry (td, cache); HandleDebugDuplicates (javaDuplicates, entry, td, cache); javaToManaged.Add (entry); managedToJava.Add (entry); + + if (uniqueAssemblies == null) { + continue; + } + + string? asmName = td.Module.Assembly.Name.Name; + if (String.IsNullOrEmpty (asmName) || uniqueAssemblies.ContainsKey (asmName)) { + continue; + } + + var asmInfo = new TypeMapDebugAssembly { + MVID = td.Module.Mvid, + Name = asmName, + }; + asmInfo.MVIDBytes = asmInfo.MVID.ToByteArray (); + uniqueAssemblies.Add (asmName, asmInfo); } SyncDebugDuplicates (javaDuplicates); - return (javaToManaged, managedToJava, foundJniNativeRegistration); + return new TypeMapDebugDataSets { + JavaToManaged = javaToManaged, + ManagedToJava = managedToJava, + UniqueAssemblies = uniqueAssemblies != null ? new List (uniqueAssemblies.Values) : null + }; } public static ReleaseGenerationState GetReleaseGenerationState (NativeCodeGenState state) diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/TypeMapGenerator.cs b/src/Xamarin.Android.Build.Tasks/Utilities/TypeMapGenerator.cs index 9511edc39fe..a9534a3b595 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/TypeMapGenerator.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/TypeMapGenerator.cs @@ -83,12 +83,27 @@ public override string ToString () } } + internal sealed class TypeMapDebugAssembly + { + public Guid MVID; + public byte[] MVIDBytes; + public string Name; + } + + internal sealed class TypeMapDebugDataSets + { + public List JavaToManaged ; + public List ManagedToJava; + public List? UniqueAssemblies; + } + // Widths include the terminating nul character but not the padding! internal sealed class ModuleDebugData { public uint EntryCount; public List JavaToManagedMap; public List ManagedToJavaMap; + public List? UniqueAssemblies; } internal sealed class ReleaseGenerationState @@ -138,18 +153,23 @@ public void Generate (bool debugBuild, bool skipJniAddNativeMethodRegistrationAt void GenerateDebugNativeAssembly (string outputDirectory) { - (var javaToManaged, var managedToJava) = state.GetDebugNativeEntries (); + TypeMapDebugDataSets dataSets = TypeMapCecilAdapter.GetDebugNativeEntries (state, needUniqueAssemblies: runtime == AndroidRuntime.CoreCLR); var data = new ModuleDebugData { - EntryCount = (uint)javaToManaged.Count, - JavaToManagedMap = javaToManaged, - ManagedToJavaMap = managedToJava, + EntryCount = (uint)dataSets.JavaToManaged.Count, + JavaToManagedMap = dataSets.JavaToManaged, + ManagedToJavaMap = dataSets.ManagedToJava, + UniqueAssemblies = dataSets.UniqueAssemblies, }; data.JavaToManagedMap.Sort ((TypeMapDebugEntry a, TypeMapDebugEntry b) => String.Compare (a.JavaName, b.JavaName, StringComparison.Ordinal)); data.ManagedToJavaMap.Sort ((TypeMapDebugEntry a, TypeMapDebugEntry b) => String.Compare (a.ManagedName, b.ManagedName, StringComparison.Ordinal)); - var composer = new TypeMappingDebugNativeAssemblyGenerator (log, data); + LLVMIR.LlvmIrComposer composer = runtime switch { + AndroidRuntime.MonoVM => new TypeMappingDebugNativeAssemblyGenerator (log, data), + AndroidRuntime.CoreCLR => new TypeMappingDebugNativeAssemblyGeneratorCLR (log, data), + _ => throw new NotSupportedException ($"Internal error: unsupported runtime {runtime}") + }; GenerateNativeAssembly (composer, composer.Construct (), outputDirectory); } diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/TypeMappingDebugNativeAssemblyGenerator.cs b/src/Xamarin.Android.Build.Tasks/Utilities/TypeMappingDebugNativeAssemblyGenerator.cs index 9b41c756387..60e52b0e06d 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/TypeMappingDebugNativeAssemblyGenerator.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/TypeMappingDebugNativeAssemblyGenerator.cs @@ -13,7 +13,7 @@ class TypeMappingDebugNativeAssemblyGenerator : LlvmIrComposer { const string JavaToManagedSymbol = "map_java_to_managed"; const string ManagedToJavaSymbol = "map_managed_to_java"; - const string TypeMapSymbol = "type_map"; // MUST match src/monodroid/xamarin-app.hh + const string TypeMapSymbol = "type_map"; // MUST match src/native/mono/xamarin-app-stub/xamarin-app.hh sealed class TypeMapContextDataProvider : NativeAssemblerStructContextDataProvider { @@ -66,11 +66,11 @@ public override string GetComment (object data, string fieldName) var entry = EnsureType (data); if (String.Compare ("from", fieldName, StringComparison.Ordinal) == 0) { - return $"from: entry.from"; + return $"from: {entry.from}"; } if (String.Compare ("to", fieldName, StringComparison.Ordinal) == 0) { - return $"to: entry.to"; + return $"to: {entry.to}"; } return String.Empty; @@ -78,7 +78,7 @@ public override string GetComment (object data, string fieldName) } // Order of fields and their type must correspond *exactly* to that in - // src/monodroid/jni/xamarin-app.hh TypeMapEntry structure + // src/native/mono/xamarin-app-stub/xamarin-app.hh TypeMapEntry structure [NativeAssemblerStructContextDataProvider (typeof (TypeMapEntryContextDataProvider))] sealed class TypeMapEntry { @@ -87,7 +87,7 @@ sealed class TypeMapEntry }; // Order of fields and their type must correspond *exactly* to that in - // src/monodroid/jni/xamarin-app.hh TypeMap structure + // src/native/mono/xamarin-app-stub/xamarin-app.hh TypeMap structure [NativeAssemblerStructContextDataProvider (typeof (TypeMapContextDataProvider))] sealed class TypeMap { diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/TypeMappingDebugNativeAssemblyGeneratorCLR.cs b/src/Xamarin.Android.Build.Tasks/Utilities/TypeMappingDebugNativeAssemblyGeneratorCLR.cs new file mode 100644 index 00000000000..bc3592ec198 --- /dev/null +++ b/src/Xamarin.Android.Build.Tasks/Utilities/TypeMappingDebugNativeAssemblyGeneratorCLR.cs @@ -0,0 +1,237 @@ +using System; +using System.Collections.Generic; + +using Microsoft.Build.Utilities; + +using Xamarin.Android.Tasks.LLVMIR; + +namespace Xamarin.Android.Tasks; + +class TypeMappingDebugNativeAssemblyGeneratorCLR : LlvmIrComposer +{ + const string JavaToManagedSymbol = "map_java_to_managed"; + const string ManagedToJavaSymbol = "map_managed_to_java"; + + // These names MUST match src/native/clr/include/xamarin-app.hh + const string TypeMapSymbol = "type_map"; + const string UniqueAssembliesSymbol = "type_map_unique_assemblies"; + const string AssemblyNamesBlobSymbol = "type_map_assembly_names_blob"; + + sealed class TypeMapContextDataProvider : NativeAssemblerStructContextDataProvider + { + public override ulong GetBufferSize (object data, string fieldName) + { + var map_module = EnsureType (data); + if (String.Compare ("java_to_managed", fieldName, StringComparison.Ordinal) == 0 || + String.Compare ("managed_to_java", fieldName, StringComparison.Ordinal) == 0) { + return map_module.entry_count; + } + + return 0; + } + + public override string GetPointedToSymbolName (object data, string fieldName) + { + var map_module = EnsureType (data); + + if (String.Compare ("java_to_managed", fieldName, StringComparison.Ordinal) == 0) { + return map_module.JavaToManagedCount == 0 ? null : JavaToManagedSymbol; + } + + if (String.Compare ("managed_to_java", fieldName, StringComparison.Ordinal) == 0) { + return map_module.ManagedToJavaCount == 0 ? null : ManagedToJavaSymbol; + } + + return base.GetPointedToSymbolName (data, fieldName); + } + } + + sealed class TypeMapEntryContextDataProvider : NativeAssemblerStructContextDataProvider + { + public override string GetComment (object data, string fieldName) + { + var entry = EnsureType (data); + + if (String.Compare ("from", fieldName, StringComparison.Ordinal) == 0) { + return $"from: {entry.from}"; + } + + if (String.Compare ("to", fieldName, StringComparison.Ordinal) == 0) { + return $"to: {entry.to}"; + } + + return String.Empty; + } + } + + sealed class TypeMapAssemblyContextDataProvider : NativeAssemblerStructContextDataProvider + { + public override string GetComment (object data, string fieldName) + { + var entry = EnsureType (data); + + if (String.Compare ("mvid_hash", fieldName, StringComparison.Ordinal) == 0) { + return $" MVID: {entry.MVID}"; + } + + if (String.Compare ("name_offset", fieldName, StringComparison.Ordinal) == 0) { + return $" {entry.Name}"; + } + + return String.Empty; + } + } + + // Order of fields and their type must correspond *exactly* to that in + // src/native/clr/include/xamarin-app.hh TypeMapEntry structure + [NativeAssemblerStructContextDataProvider (typeof (TypeMapEntryContextDataProvider))] + sealed class TypeMapEntry + { + [NativeAssembler (UsesDataProvider = true)] + public string from; + + [NativeAssembler (UsesDataProvider = true)] + public string to; + }; + + // Order of fields and their type must correspond *exactly* to that in + // src/native/clr/include/xamarin-app.hh TypeMap structure + [NativeAssemblerStructContextDataProvider (typeof (TypeMapContextDataProvider))] + sealed class TypeMap + { + [NativeAssembler (Ignore = true)] + public int JavaToManagedCount; + + [NativeAssembler (Ignore = true)] + public int ManagedToJavaCount; + + public uint entry_count; + public ulong unique_assemblies_count; + public ulong assembly_names_blob_size; + + [NativeAssembler (UsesDataProvider = true), NativePointer (PointsToSymbol = "")] + public TypeMapEntry? java_to_managed = null; + + [NativeAssembler (UsesDataProvider = true), NativePointer (PointsToSymbol = "")] + public TypeMapEntry? managed_to_java = null; + }; + + // Order of fields and their type must correspond *exactly* to that in + // src/native/clr/include/xamarin-app.hh TypeMapAssembly structure + [NativeAssemblerStructContextDataProvider (typeof (TypeMapAssemblyContextDataProvider))] + sealed class TypeMapAssembly + { + [NativeAssembler (Ignore = true)] + public string Name; + + [NativeAssembler (Ignore = true)] + public Guid MVID; + + [NativeAssembler (UsesDataProvider = true, NumberFormat = LlvmIrVariableNumberFormat.Hexadecimal)] + public ulong mvid_hash; + public ulong name_length; + + [NativeAssembler (UsesDataProvider = true)] + public ulong name_offset; + } + + readonly TypeMapGenerator.ModuleDebugData data; + StructureInfo typeMapEntryStructureInfo; + StructureInfo typeMapStructureInfo; + StructureInfo typeMapAssemblyStructureInfo; + List> javaToManagedMap; + List> managedToJavaMap; + List> uniqueAssemblies; + StructureInstance type_map; + + public TypeMappingDebugNativeAssemblyGeneratorCLR (TaskLoggingHelper log, TypeMapGenerator.ModuleDebugData data) + : base (log) + { + if (data.UniqueAssemblies == null || data.UniqueAssemblies.Count == 0) { + throw new InvalidOperationException ("Internal error: set of unique assemblies must be provided."); + } + + this.data = data; + + javaToManagedMap = new (); + managedToJavaMap = new (); + uniqueAssemblies = new (); + } + + protected override void Construct (LlvmIrModule module) + { + module.DefaultStringGroup = "tmd"; + + MapStructures (module); + + if (data.ManagedToJavaMap != null && data.ManagedToJavaMap.Count > 0) { + foreach (TypeMapGenerator.TypeMapDebugEntry entry in data.ManagedToJavaMap) { + var m2j = new TypeMapEntry { + from = entry.ManagedName, + to = entry.JavaName, + }; + managedToJavaMap.Add (new StructureInstance (typeMapEntryStructureInfo, m2j)); + } + } + + if (data.JavaToManagedMap != null && data.JavaToManagedMap.Count > 0) { + foreach (TypeMapGenerator.TypeMapDebugEntry entry in data.JavaToManagedMap) { + TypeMapGenerator.TypeMapDebugEntry managedEntry = entry.DuplicateForJavaToManaged != null ? entry.DuplicateForJavaToManaged : entry; + + var j2m = new TypeMapEntry { + from = entry.JavaName, + to = managedEntry.SkipInJavaToManaged ? null : managedEntry.ManagedName, + }; + javaToManagedMap.Add (new StructureInstance (typeMapEntryStructureInfo, j2m)); + } + } + + // CoreCLR supports only 64-bit targets, so we can make things simpler by hashing the MVIDs here instead of + // in a callback during code generation + var assemblyNamesBlob = new List (); + foreach (TypeMapGenerator.TypeMapDebugAssembly asm in data.UniqueAssemblies) { + byte[] nameBytes = MonoAndroidHelper.Utf8StringToBytes (asm.Name); + var entry = new TypeMapAssembly { + Name = asm.Name, + MVID = asm.MVID, + + mvid_hash = MonoAndroidHelper.GetXxHash (asm.MVIDBytes, is64Bit: true), + name_length = (ulong)nameBytes.Length, // without the trailing NUL + name_offset = (ulong)assemblyNamesBlob.Count, + }; + uniqueAssemblies.Add (new StructureInstance (typeMapAssemblyStructureInfo, entry)); + assemblyNamesBlob.AddRange (nameBytes); + assemblyNamesBlob.Add (0); + } + uniqueAssemblies.Sort ((StructureInstance a, StructureInstance b) => a.Instance.mvid_hash.CompareTo (b.Instance.mvid_hash)); + + var map = new TypeMap { + JavaToManagedCount = data.JavaToManagedMap == null ? 0 : data.JavaToManagedMap.Count, + ManagedToJavaCount = data.ManagedToJavaMap == null ? 0 : data.ManagedToJavaMap.Count, + + entry_count = data.EntryCount, + unique_assemblies_count = (ulong)data.UniqueAssemblies.Count, + assembly_names_blob_size = (ulong)assemblyNamesBlob.Count, + }; + type_map = new StructureInstance (typeMapStructureInfo, map); + module.AddGlobalVariable (TypeMapSymbol, type_map, LlvmIrVariableOptions.GlobalConstant); + + if (managedToJavaMap.Count > 0) { + module.AddGlobalVariable (ManagedToJavaSymbol, managedToJavaMap, LlvmIrVariableOptions.LocalConstant); + } + + if (javaToManagedMap.Count > 0) { + module.AddGlobalVariable (JavaToManagedSymbol, javaToManagedMap, LlvmIrVariableOptions.LocalConstant); + } + + module.AddGlobalVariable (UniqueAssembliesSymbol, uniqueAssemblies, LlvmIrVariableOptions.GlobalConstant); + module.AddGlobalVariable (AssemblyNamesBlobSymbol, assemblyNamesBlob, LlvmIrVariableOptions.GlobalConstant); + } + + void MapStructures (LlvmIrModule module) + { + typeMapAssemblyStructureInfo = module.MapStructure (); + typeMapEntryStructureInfo = module.MapStructure (); + typeMapStructureInfo = module.MapStructure (); + } +} diff --git a/src/native/clr/host/typemap.cc b/src/native/clr/host/typemap.cc index 605a14930e8..31b82435e79 100644 --- a/src/native/clr/host/typemap.cc +++ b/src/native/clr/host/typemap.cc @@ -67,6 +67,7 @@ namespace { [[gnu::always_inline]] auto TypeMapper::typemap_type_to_type_debug (const char *typeName, const TypeMapEntry *map, std::string_view const& from_name, std::string_view const& to_name) noexcept -> const char* { + log_debug (LOG_ASSEMBLY, "Looking up {} type '{}'", from_name, optional_string (typeName)); auto equal = [](TypeMapEntry const& entry, const char *key) -> bool { if (entry.from == nullptr) { return 1; @@ -100,7 +101,7 @@ auto TypeMapper::typemap_type_to_type_debug (const char *typeName, const TypeMap } [[gnu::always_inline]] -auto TypeMapper::typemap_managed_to_java_debug (const char *typeName) noexcept -> const char* +auto TypeMapper::typemap_managed_to_java_debug (const char *typeName, const uint8_t *mvid) noexcept -> const char* { return typemap_type_to_type_debug (typeName, type_map.managed_to_java, MANAGED, JAVA); } @@ -243,7 +244,7 @@ auto TypeMapper::typemap_managed_to_java_release (const char *typeName, const ui #endif // def RELEASE [[gnu::flatten]] -auto TypeMapper::typemap_managed_to_java (const char *typeName, [[maybe_unused]] const uint8_t *mvid) noexcept -> const char* +auto TypeMapper::typemap_managed_to_java (const char *typeName, const uint8_t *mvid) noexcept -> const char* { log_debug (LOG_ASSEMBLY, "typemap_managed_to_java: looking up type '{}'", optional_string (typeName)); if (FastTiming::enabled ()) [[unlikely]] { @@ -259,7 +260,7 @@ auto TypeMapper::typemap_managed_to_java (const char *typeName, [[maybe_unused]] #if defined(RELEASE) ret = typemap_managed_to_java_release (typeName, mvid); #else - ret = typemap_managed_to_java_debug (typeName); + ret = typemap_managed_to_java_debug (typeName, mvid); #endif if (FastTiming::enabled ()) [[unlikely]] { diff --git a/src/native/clr/include/host/typemap.hh b/src/native/clr/include/host/typemap.hh index 79320555305..fa15db569cf 100644 --- a/src/native/clr/include/host/typemap.hh +++ b/src/native/clr/include/host/typemap.hh @@ -28,7 +28,7 @@ namespace xamarin::android { static auto find_java_to_managed_entry (hash_t name_hash) noexcept -> const TypeMapJava*; #else static auto typemap_type_to_type_debug (const char *typeName, const TypeMapEntry *map, std::string_view const& from_name, std::string_view const& to_name) noexcept -> const char*; - static auto typemap_managed_to_java_debug (const char *typeName) noexcept -> const char*; + static auto typemap_managed_to_java_debug (const char *typeName, const uint8_t *mvid) noexcept -> const char*; static auto typemap_java_to_managed_debug (const char *java_type_name, char const** assembly_name, uint32_t *managed_type_token_id) noexcept -> bool; #endif }; diff --git a/src/native/clr/include/xamarin-app.hh b/src/native/clr/include/xamarin-app.hh index 5b2ad4cd963..34ca1f7ea7d 100644 --- a/src/native/clr/include/xamarin-app.hh +++ b/src/native/clr/include/xamarin-app.hh @@ -62,15 +62,22 @@ struct TypeMapEntry const char *to; }; -// MUST match src/Xamarin.Android.Build.Tasks/Utilities/TypeMappingDebugNativeAssemblyGenerator.cs +// MUST match src/Xamarin.Android.Build.Tasks/Utilities/TypeMappingDebugNativeAssemblyGeneratorCLR.cs struct TypeMap { uint32_t entry_count; - char *assembly_name; - uint8_t *data; + uint64_t unique_assemblies_count; + uint64_t assembly_names_blob_size; const TypeMapEntry *java_to_managed; const TypeMapEntry *managed_to_java; }; + +struct TypeMapAssembly +{ + xamarin::android::hash_t mvid_hash; + uint64_t name_length; + uint64_t name_offset; // into the assembly names blob +}; #else struct TypeMapModuleEntry { @@ -312,7 +319,9 @@ extern "C" { [[gnu::visibility("default")]] extern const uint64_t format_tag; #if defined (DEBUG) - [[gnu::visibility("default")]] extern const TypeMap type_map; // MUST match src/Xamarin.Android.Build.Tasks/Utilities/TypeMappingDebugNativeAssemblyGenerator.cs + [[gnu::visibility("default")]] extern const TypeMap type_map; // MUST match src/Xamarin.Android.Build.Tasks/Utilities/TypeMappingDebugNativeAssemblyGeneratorCLR.cs + [[gnu::visibility("default")]] extern const TypeMapAssembly type_map_unique_assemblies; + [[gnu::visibility("default")]] extern const char type_map_assembly_names_blob[]; #else [[gnu::visibility("default")]] extern const uint32_t managed_to_java_map_module_count; [[gnu::visibility("default")]] extern const uint32_t java_type_count; diff --git a/src/native/clr/xamarin-app-stub/application_dso_stub.cc b/src/native/clr/xamarin-app-stub/application_dso_stub.cc index e16929d2c3a..d240b547618 100644 --- a/src/native/clr/xamarin-app-stub/application_dso_stub.cc +++ b/src/native/clr/xamarin-app-stub/application_dso_stub.cc @@ -15,11 +15,11 @@ static TypeMapEntry managed_to_java[] = {}; // MUST match src/Xamarin.Android.Build.Tasks/Utilities/TypeMappingDebugNativeAssemblyGenerator.cs const TypeMap type_map = { - 0, - nullptr, - nullptr, - java_to_managed, - managed_to_java + .entry_count = 0, + .unique_assemblies_count = 0, + .assembly_names_blob_size = 0, + .java_to_managed = java_to_managed, + .managed_to_java = managed_to_java, }; #else const uint32_t managed_to_java_map_module_count = 0; From 5084e794dd7ff958312754baa9144caa36a48a49 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 23 Apr 2025 20:09:35 +0200 Subject: [PATCH 06/14] A handful of fixlets, typemap appears to work fine now --- src/native/clr/host/internal-pinvokes.cc | 2 ++ src/native/clr/host/typemap.cc | 24 ++++++++++++++++--- src/native/clr/include/xamarin-app.hh | 2 +- .../xamarin-app-stub/application_dso_stub.cc | 3 +++ src/native/common/include/shared/xxhash.hh | 4 ++-- 5 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/native/clr/host/internal-pinvokes.cc b/src/native/clr/host/internal-pinvokes.cc index 4d801afe032..4a3a21fd6d7 100644 --- a/src/native/clr/host/internal-pinvokes.cc +++ b/src/native/clr/host/internal-pinvokes.cc @@ -28,11 +28,13 @@ void _monodroid_gref_log_delete (jobject handle, char type, const char *threadNa const char* clr_typemap_managed_to_java (const char *typeName, const uint8_t *mvid) noexcept { + log_debug (LOG_DEFAULT, __PRETTY_FUNCTION__); return TypeMapper::typemap_managed_to_java (typeName, mvid); } bool clr_typemap_java_to_managed (const char *java_type_name, char const** assembly_name, uint32_t *managed_type_token_id) noexcept { + log_debug (LOG_DEFAULT, __PRETTY_FUNCTION__); return TypeMapper::typemap_java_to_managed (java_type_name, assembly_name, managed_type_token_id); } diff --git a/src/native/clr/host/typemap.cc b/src/native/clr/host/typemap.cc index 31b82435e79..3ebfd95a1c2 100644 --- a/src/native/clr/host/typemap.cc +++ b/src/native/clr/host/typemap.cc @@ -73,7 +73,7 @@ auto TypeMapper::typemap_type_to_type_debug (const char *typeName, const TypeMap return 1; } - return strcmp (key, entry.from) == 0; + return strcmp (entry.from, key) == 0; }; auto less_than = [](TypeMapEntry const& entry, const char *key) -> bool { @@ -81,7 +81,7 @@ auto TypeMapper::typemap_type_to_type_debug (const char *typeName, const TypeMap return 1; } - return strcmp (key, entry.from); + return strcmp (entry.from, key) < 0; }; ssize_t idx = Search::binary_search (typeName, map, type_map.entry_count); @@ -103,7 +103,25 @@ auto TypeMapper::typemap_type_to_type_debug (const char *typeName, const TypeMap [[gnu::always_inline]] auto TypeMapper::typemap_managed_to_java_debug (const char *typeName, const uint8_t *mvid) noexcept -> const char* { - return typemap_type_to_type_debug (typeName, type_map.managed_to_java, MANAGED, JAVA); + dynamic_local_path_string full_type_name; + full_type_name.append (typeName); + + hash_t mvid_hash = xxhash::hash (mvid, 16z); // we must hope managed land called us with valid data + + auto equal = [](TypeMapAssembly const& entry, hash_t key) -> bool { return entry.mvid_hash == key; }; + auto less_than = [](TypeMapAssembly const& entry, hash_t key) -> bool { return entry.mvid_hash < key; }; + ssize_t idx = Search::binary_search (mvid_hash, type_map_unique_assemblies, type_map.unique_assemblies_count); + + if (idx >= 0) [[likely]] { + TypeMapAssembly const& assm = type_map_unique_assemblies[idx]; + full_type_name.append (", "sv); + full_type_name.append (&type_map_assembly_names_blob[assm.name_offset], assm.name_length); + log_debug (LOG_ASSEMBLY, "Fixed-up type name: '{}'", full_type_name.get ()); + } else { + log_warn (LOG_ASSEMBLY, "Unable to look up assembly name for type '{}', trying without it.", typeName); + } + + return typemap_type_to_type_debug (full_type_name.get (), type_map.managed_to_java, MANAGED, JAVA); } #endif // def DEBUG diff --git a/src/native/clr/include/xamarin-app.hh b/src/native/clr/include/xamarin-app.hh index 34ca1f7ea7d..b8717e5e7eb 100644 --- a/src/native/clr/include/xamarin-app.hh +++ b/src/native/clr/include/xamarin-app.hh @@ -320,7 +320,7 @@ extern "C" { #if defined (DEBUG) [[gnu::visibility("default")]] extern const TypeMap type_map; // MUST match src/Xamarin.Android.Build.Tasks/Utilities/TypeMappingDebugNativeAssemblyGeneratorCLR.cs - [[gnu::visibility("default")]] extern const TypeMapAssembly type_map_unique_assemblies; + [[gnu::visibility("default")]] extern const TypeMapAssembly type_map_unique_assemblies[]; [[gnu::visibility("default")]] extern const char type_map_assembly_names_blob[]; #else [[gnu::visibility("default")]] extern const uint32_t managed_to_java_map_module_count; diff --git a/src/native/clr/xamarin-app-stub/application_dso_stub.cc b/src/native/clr/xamarin-app-stub/application_dso_stub.cc index d240b547618..146414e0dc4 100644 --- a/src/native/clr/xamarin-app-stub/application_dso_stub.cc +++ b/src/native/clr/xamarin-app-stub/application_dso_stub.cc @@ -21,6 +21,9 @@ const TypeMap type_map = { .java_to_managed = java_to_managed, .managed_to_java = managed_to_java, }; + +const TypeMapAssembly type_map_unique_assemblies[] = {}; +const char type_map_assembly_names_blob[] = {}; #else const uint32_t managed_to_java_map_module_count = 0; const uint32_t java_type_count = 0; diff --git a/src/native/common/include/shared/xxhash.hh b/src/native/common/include/shared/xxhash.hh index 32365aceab0..a2760604862 100644 --- a/src/native/common/include/shared/xxhash.hh +++ b/src/native/common/include/shared/xxhash.hh @@ -163,8 +163,8 @@ namespace xamarin::android class xxhash64 final { public: - [[gnu::always_inline]] - static auto hash (const char *p, size_t len) noexcept -> XXH64_hash_t + template [[gnu::always_inline]] + static auto hash (const T *p, size_t len) noexcept -> XXH64_hash_t { return XXH3_64bits (static_cast(p), len); } From d556a02282a4c587f0563d54ce2c041dadc5b044 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Thu, 24 Apr 2025 11:11:36 +0200 Subject: [PATCH 07/14] Remove some debug stuff --- src/native/clr/host/internal-pinvokes.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/native/clr/host/internal-pinvokes.cc b/src/native/clr/host/internal-pinvokes.cc index 4a3a21fd6d7..4d801afe032 100644 --- a/src/native/clr/host/internal-pinvokes.cc +++ b/src/native/clr/host/internal-pinvokes.cc @@ -28,13 +28,11 @@ void _monodroid_gref_log_delete (jobject handle, char type, const char *threadNa const char* clr_typemap_managed_to_java (const char *typeName, const uint8_t *mvid) noexcept { - log_debug (LOG_DEFAULT, __PRETTY_FUNCTION__); return TypeMapper::typemap_managed_to_java (typeName, mvid); } bool clr_typemap_java_to_managed (const char *java_type_name, char const** assembly_name, uint32_t *managed_type_token_id) noexcept { - log_debug (LOG_DEFAULT, __PRETTY_FUNCTION__); return TypeMapper::typemap_java_to_managed (java_type_name, assembly_name, managed_type_token_id); } From 9fbe2565a1f5486ac5cbca675e84816f53d37bc0 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Fri, 25 Apr 2025 09:54:32 +0200 Subject: [PATCH 08/14] Remove duplicate timing --- src/native/clr/host/typemap.cc | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/native/clr/host/typemap.cc b/src/native/clr/host/typemap.cc index 3ebfd95a1c2..43194203261 100644 --- a/src/native/clr/host/typemap.cc +++ b/src/native/clr/host/typemap.cc @@ -313,10 +313,6 @@ auto TypeMapper::find_java_to_managed_entry (hash_t name_hash) noexcept -> const [[gnu::flatten]] auto TypeMapper::typemap_java_to_managed_release (const char *java_type_name, char const** assembly_name, uint32_t *managed_type_token_id) noexcept -> bool { - if (FastTiming::enabled ()) [[unlikely]] { - internal_timing.start_event (TimingEventKind::JavaToManaged); - } - if (java_type_name == nullptr || assembly_name == nullptr || managed_type_token_id == nullptr) [[unlikely]] { if (java_type_name == nullptr) { log_warn ( @@ -374,10 +370,6 @@ auto TypeMapper::typemap_java_to_managed_release (const char *java_type_name, ch optional_string (*assembly_name) ); - if (FastTiming::enabled ()) [[unlikely]] { - internal_timing.end_event (); - } - return true; } #endif // ndef DEBUG From 9f7eb422a2b2d506f4faa7678db9f163755a2e04 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Fri, 25 Apr 2025 09:57:40 +0200 Subject: [PATCH 09/14] Fix after rebase --- .../Xamarin.Android.Common.targets | 38 ++----------------- 1 file changed, 4 insertions(+), 34 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index 511945a4009..9333ac64189 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -1873,39 +1873,9 @@ because xbuild doesn't support framework reference assemblies. + MainAssembly="$(TargetPath)" + OutputDirectory="$(_AndroidIntermediateJavaSourceDirectory)mono" + ResolvedUserAssemblies="@(_ResolvedUserAssemblies)"> Date: Wed, 30 Apr 2025 14:14:04 +0200 Subject: [PATCH 10/14] Fix after rebase --- .../Utilities/TypeMapCecilAdapter.cs | 17 ++++++++--------- .../Utilities/TypeMapGenerator.cs | 16 ++++++++++------ 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/TypeMapCecilAdapter.cs b/src/Xamarin.Android.Build.Tasks/Utilities/TypeMapCecilAdapter.cs index 9aad6e4c2cc..40584a8ac49 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/TypeMapCecilAdapter.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/TypeMapCecilAdapter.cs @@ -17,24 +17,23 @@ class TypeMapCecilAdapter { public static TypeMapDebugDataSets GetDebugNativeEntries (NativeCodeGenState state, bool needUniqueAssemblies) { - var (javaToManaged, managedToJava, foundJniNativeRegistration) = GetDebugNativeEntries (state.AllJavaTypes, state.TypeCache); + var (TypeMapDebugDataSets dataSets, foundJniNativeRegistration) = GetDebugNativeEntries (state.AllJavaTypes, state.TypeCache); state.JniAddNativeMethodRegistrationAttributePresent = foundJniNativeRegistration; - return (javaToManaged, managedToJava); + return dataSets; } - public static (List javaToManaged, List managedToJava, bool foundJniNativeRegistration) GetDebugNativeEntries (List types, TypeDefinitionCache cache) + public static (TypeMapDebugDataSets dataSets, bool foundJniNativeRegistration) GetDebugNativeEntries (List types, TypeDefinitionCache cache) { var javaDuplicates = new Dictionary> (StringComparer.Ordinal); + var uniqueAssemblies = needUniqueAssemblies ? new Dictionary (StringComparer.OrdinalIgnoreCase) : null; var javaToManaged = new List (); var managedToJava = new List (); var foundJniNativeRegistration = false; - var javaDuplicates = new Dictionary> (StringComparer.Ordinal); - var uniqueAssemblies = needUniqueAssemblies ? new Dictionary (StringComparer.OrdinalIgnoreCase) : null; - foreach (TypeDefinition td in state.AllJavaTypes) { - UpdateApplicationConfig (state, td); + foreach (var td in types) { + foundJniNativeRegistration = JniAddNativeMethodRegistrationAttributeFound (foundJniNativeRegistration, td); TypeMapDebugEntry entry = GetDebugEntry (td, cache); HandleDebugDuplicates (javaDuplicates, entry, td, cache); @@ -61,11 +60,11 @@ public static (List javaToManaged, List ma SyncDebugDuplicates (javaDuplicates); - return new TypeMapDebugDataSets { + return (new TypeMapDebugDataSets { JavaToManaged = javaToManaged, ManagedToJava = managedToJava, UniqueAssemblies = uniqueAssemblies != null ? new List (uniqueAssemblies.Values) : null - }; + }, foundJniNativeRegistration); } public static ReleaseGenerationState GetReleaseGenerationState (NativeCodeGenState state) diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/TypeMapGenerator.cs b/src/Xamarin.Android.Build.Tasks/Utilities/TypeMapGenerator.cs index a9534a3b595..b1efeaee168 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/TypeMapGenerator.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/TypeMapGenerator.cs @@ -153,7 +153,7 @@ public void Generate (bool debugBuild, bool skipJniAddNativeMethodRegistrationAt void GenerateDebugNativeAssembly (string outputDirectory) { - TypeMapDebugDataSets dataSets = TypeMapCecilAdapter.GetDebugNativeEntries (state, needUniqueAssemblies: runtime == AndroidRuntime.CoreCLR); + TypeMapDebugDataSets dataSets = state.GetDebugNativeEntries (needUniqueAssemblies: runtime == AndroidRuntime.CoreCLR); var data = new ModuleDebugData { EntryCount = (uint)dataSets.JavaToManaged.Count, @@ -236,7 +236,7 @@ interface ITypeMapGeneratorAdapter { AndroidTargetArch TargetArch { get; } bool JniAddNativeMethodRegistrationAttributePresent { get; set; } - (List javaToManaged, List managedToJava) GetDebugNativeEntries (); + TypeMapDebugDataSets GetDebugNativeEntries (bool needUniqueAssemblies); ReleaseGenerationState GetReleaseGenerationState (); } @@ -256,9 +256,9 @@ public bool JniAddNativeMethodRegistrationAttributePresent { set => state.JniAddNativeMethodRegistrationAttributePresent = value; } - public (List javaToManaged, List managedToJava) GetDebugNativeEntries () + public TypeMapDebugDataSets GetDebugNativeEntries (bool needUniqueAssemblies) { - return TypeMapCecilAdapter.GetDebugNativeEntries (state); + return TypeMapCecilAdapter.GetDebugNativeEntries (state, needUniqueAssemblies); } public ReleaseGenerationState GetReleaseGenerationState () @@ -279,7 +279,7 @@ public TypeMapObjectsFileAdapter (AndroidTargetArch targetArch) public bool JniAddNativeMethodRegistrationAttributePresent { get; set; } - public (List javaToManaged, List managedToJava) GetDebugNativeEntries () + public TypeMapDebugDataSets GetDebugNativeEntries (bool needUniqueAssemblies) { var javaToManaged = new List (); var managedToJava = new List (); @@ -293,7 +293,11 @@ public TypeMapObjectsFileAdapter (AndroidTargetArch targetArch) GroupDuplicateDebugEntries (javaToManaged); GroupDuplicateDebugEntries (managedToJava); - return (javaToManaged, managedToJava); + return new TypeMapDebugDataSets { + JavaToManaged = javaToManaged, + ManagedToJava = managedToJava, + UniqueAssemblies = null, + } } void GroupDuplicateDebugEntries (List debugEntries) From 96f59a62d84f5a50984e817e3e8628c98b65e2f3 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 30 Apr 2025 18:09:09 +0200 Subject: [PATCH 11/14] Fixes after rebase on `main` --- .../MonoDroid.Tuner/FindTypeMapObjectsStep.cs | 7 ++++--- .../Utilities/TypeMapCecilAdapter.cs | 6 +++--- .../Utilities/TypeMapGenerator.cs | 14 ++++++++++++-- .../Utilities/TypeMapObjectsXmlFile.cs | 7 +++++++ 4 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FindTypeMapObjectsStep.cs b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FindTypeMapObjectsStep.cs index 68ab3e6bd6e..08863825ef9 100644 --- a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FindTypeMapObjectsStep.cs +++ b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FindTypeMapObjectsStep.cs @@ -37,13 +37,14 @@ public void ProcessAssembly (AssemblyDefinition assembly, StepContext context) var xml = new TypeMapObjectsXmlFile { AssemblyName = assembly.Name.Name, + AssemblyMvid = assembly.MainModule.Mvid, }; if (Debug) { - var (javaToManaged, managedToJava, foundJniNativeRegistration) = TypeMapCecilAdapter.GetDebugNativeEntries (types, Context); + var (typeMapDebugSets, foundJniNativeRegistration) = TypeMapCecilAdapter.GetDebugNativeEntries (types, Context, needUniqueAssemblies: false); - xml.JavaToManagedDebugEntries.AddRange (javaToManaged); - xml.ManagedToJavaDebugEntries.AddRange (managedToJava); + xml.JavaToManagedDebugEntries.AddRange (typeMapDebugSets.JavaToManaged); + xml.ManagedToJavaDebugEntries.AddRange (typeMapDebugSets.ManagedToJava); xml.FoundJniNativeRegistration = foundJniNativeRegistration; } else { var genState = TypeMapCecilAdapter.GetReleaseGenerationState (types, Context, out var foundJniNativeRegistration); diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/TypeMapCecilAdapter.cs b/src/Xamarin.Android.Build.Tasks/Utilities/TypeMapCecilAdapter.cs index 40584a8ac49..fc6b4930af4 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/TypeMapCecilAdapter.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/TypeMapCecilAdapter.cs @@ -17,14 +17,14 @@ class TypeMapCecilAdapter { public static TypeMapDebugDataSets GetDebugNativeEntries (NativeCodeGenState state, bool needUniqueAssemblies) { - var (TypeMapDebugDataSets dataSets, foundJniNativeRegistration) = GetDebugNativeEntries (state.AllJavaTypes, state.TypeCache); + var (dataSets, foundJniNativeRegistration) = GetDebugNativeEntries (state.AllJavaTypes, state.TypeCache, needUniqueAssemblies); state.JniAddNativeMethodRegistrationAttributePresent = foundJniNativeRegistration; return dataSets; } - public static (TypeMapDebugDataSets dataSets, bool foundJniNativeRegistration) GetDebugNativeEntries (List types, TypeDefinitionCache cache) + public static (TypeMapDebugDataSets dataSets, bool foundJniNativeRegistration) GetDebugNativeEntries (List types, TypeDefinitionCache cache, bool needUniqueAssemblies) { var javaDuplicates = new Dictionary> (StringComparer.Ordinal); var uniqueAssemblies = needUniqueAssemblies ? new Dictionary (StringComparer.OrdinalIgnoreCase) : null; @@ -227,7 +227,7 @@ static bool JniAddNativeMethodRegistrationAttributeFound (bool alreadyFound, Typ if (alreadyFound || !javaType.HasCustomAttributes) { return alreadyFound; } - + foreach (CustomAttribute ca in javaType.CustomAttributes) { if (string.Equals ("JniAddNativeMethodRegistrationAttribute", ca.AttributeType.Name, StringComparison.Ordinal)) { return true; diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/TypeMapGenerator.cs b/src/Xamarin.Android.Build.Tasks/Utilities/TypeMapGenerator.cs index b1efeaee168..56b33164d33 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/TypeMapGenerator.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/TypeMapGenerator.cs @@ -283,8 +283,18 @@ public TypeMapDebugDataSets GetDebugNativeEntries (bool needUniqueAssemblies) { var javaToManaged = new List (); var managedToJava = new List (); + var uniqueAssemblies = new Dictionary (StringComparer.OrdinalIgnoreCase); foreach (var xml in XmlFiles) { + if (!uniqueAssemblies.ContainsKey (xml.AssemblyName)) { + var assm = new TypeMapDebugAssembly { + MVID = xml.AssemblyMvid, + MVIDBytes = xml.AssemblyMvid.ToByteArray (), + Name = xml.AssemblyName, + }; + uniqueAssemblies.Add (xml.AssemblyName, assm); + } + javaToManaged.AddRange (xml.JavaToManagedDebugEntries); managedToJava.AddRange (xml.ManagedToJavaDebugEntries); } @@ -296,8 +306,8 @@ public TypeMapDebugDataSets GetDebugNativeEntries (bool needUniqueAssemblies) return new TypeMapDebugDataSets { JavaToManaged = javaToManaged, ManagedToJava = managedToJava, - UniqueAssemblies = null, - } + UniqueAssemblies = uniqueAssemblies.Values.ToList (), + }; } void GroupDuplicateDebugEntries (List debugEntries) diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/TypeMapObjectsXmlFile.cs b/src/Xamarin.Android.Build.Tasks/Utilities/TypeMapObjectsXmlFile.cs index 5af39a6d0d2..9eb190dabc0 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/TypeMapObjectsXmlFile.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/TypeMapObjectsXmlFile.cs @@ -25,6 +25,7 @@ class TypeMapObjectsXmlFile static readonly TypeMapObjectsXmlFile unscanned = new TypeMapObjectsXmlFile { WasScanned = false }; public string? AssemblyName { get; set; } + public Guid AssemblyMvid { get; set; } = Guid.Empty; public bool FoundJniNativeRegistration { get; set; } public List JavaToManagedDebugEntries { get; } = []; public List ManagedToJavaDebugEntries { get; } = []; @@ -58,6 +59,10 @@ void Export (XmlWriter xml) xml.WriteStartElement ("api"); xml.WriteAttributeString ("type", HasDebugEntries ? "debug" : "release"); xml.WriteAttributeStringIfNotDefault ("assembly-name", AssemblyName); + + if (AssemblyMvid != Guid.Empty) { + xml.WriteAttributeString ("mvid", AssemblyMvid.ToString ("N")); + } xml.WriteAttributeStringIfNotDefault ("found-jni-native-registration", FoundJniNativeRegistration); if (HasDebugEntries) @@ -173,11 +178,13 @@ public static TypeMapObjectsXmlFile Import (string filename) var type = root.GetRequiredAttribute ("type"); var assemblyName = root.GetAttributeOrDefault ("assembly-name", (string?)null); + var mvid = Guid.Parse (root.GetAttributeOrDefault ("mvid", Guid.Empty.ToString ())); var foundJniNativeRegistration = root.GetAttributeOrDefault ("found-jni-native-registration", false); var file = new TypeMapObjectsXmlFile { WasScanned = true, AssemblyName = assemblyName, + AssemblyMvid = mvid, FoundJniNativeRegistration = foundJniNativeRegistration, }; From 140bf0dcf81ed35f6b15ca68eff7b6f2c2b9b78f Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 5 May 2025 13:06:38 +0200 Subject: [PATCH 12/14] Fix nullable issues after rebase on `main` --- ...eMappingDebugNativeAssemblyGeneratorCLR.cs | 32 +++++++++++++------ 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/TypeMappingDebugNativeAssemblyGeneratorCLR.cs b/src/Xamarin.Android.Build.Tasks/Utilities/TypeMappingDebugNativeAssemblyGeneratorCLR.cs index bc3592ec198..63506cdb4bd 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/TypeMappingDebugNativeAssemblyGeneratorCLR.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/TypeMappingDebugNativeAssemblyGeneratorCLR.cs @@ -30,7 +30,7 @@ public override ulong GetBufferSize (object data, string fieldName) return 0; } - public override string GetPointedToSymbolName (object data, string fieldName) + public override string? GetPointedToSymbolName (object data, string fieldName) { var map_module = EnsureType (data); @@ -88,10 +88,10 @@ public override string GetComment (object data, string fieldName) sealed class TypeMapEntry { [NativeAssembler (UsesDataProvider = true)] - public string from; + public string from = String.Empty; [NativeAssembler (UsesDataProvider = true)] - public string to; + public string? to; }; // Order of fields and their type must correspond *exactly* to that in @@ -122,7 +122,7 @@ sealed class TypeMap sealed class TypeMapAssembly { [NativeAssembler (Ignore = true)] - public string Name; + public string Name = String.Empty; [NativeAssembler (Ignore = true)] public Guid MVID; @@ -136,13 +136,13 @@ sealed class TypeMapAssembly } readonly TypeMapGenerator.ModuleDebugData data; - StructureInfo typeMapEntryStructureInfo; - StructureInfo typeMapStructureInfo; - StructureInfo typeMapAssemblyStructureInfo; + StructureInfo? typeMapEntryStructureInfo; + StructureInfo? typeMapStructureInfo; + StructureInfo? typeMapAssemblyStructureInfo; List> javaToManagedMap; List> managedToJavaMap; List> uniqueAssemblies; - StructureInstance type_map; + StructureInstance? type_map; public TypeMappingDebugNativeAssemblyGeneratorCLR (TaskLoggingHelper log, TypeMapGenerator.ModuleDebugData data) : base (log) @@ -162,6 +162,10 @@ protected override void Construct (LlvmIrModule module) { module.DefaultStringGroup = "tmd"; + if (data.UniqueAssemblies == null) { + throw new InvalidOperationException ("Internal error: unique assemblies collection must be present"); + } + MapStructures (module); if (data.ManagedToJavaMap != null && data.ManagedToJavaMap.Count > 0) { @@ -203,7 +207,17 @@ protected override void Construct (LlvmIrModule module) assemblyNamesBlob.AddRange (nameBytes); assemblyNamesBlob.Add (0); } - uniqueAssemblies.Sort ((StructureInstance a, StructureInstance b) => a.Instance.mvid_hash.CompareTo (b.Instance.mvid_hash)); + uniqueAssemblies.Sort ((StructureInstance a, StructureInstance b) => { + if (a.Instance == null) { + return b.Instance == null ? 0 : -1; + } + + if (b.Instance == null) { + return 1; + } + + return a.Instance.mvid_hash.CompareTo (b.Instance.mvid_hash); + }); var map = new TypeMap { JavaToManagedCount = data.JavaToManagedMap == null ? 0 : data.JavaToManagedMap.Count, From cadb09f87f28a193c9fe2e75904fffa8ca4db0db Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 5 May 2025 13:11:41 +0200 Subject: [PATCH 13/14] Enable Debug CoreCLR runs for some smoke tests --- .../Tests/Xamarin.Android.Build.Tests/AssetPackTests.cs | 4 ++++ .../BuildTest.TestCaseSource.cs | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AssetPackTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AssetPackTests.cs index 32e9806f3a1..9d815c33d1b 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AssetPackTests.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AssetPackTests.cs @@ -38,6 +38,7 @@ public void BuildLibraryWithAssetPack ([Values (true, false)] bool isRelease) [Category ("SmokeTests")] [TestCase (false, AndroidRuntime.MonoVM)] [TestCase (true, AndroidRuntime.MonoVM)] + [TestCase (false, AndroidRuntime.CoreCLR)] [TestCase (true, AndroidRuntime.CoreCLR)] [TestCase (true, AndroidRuntime.NativeAOT)] public void BuildApplicationWithAssetPackThatHasInvalidName (bool isRelease, AndroidRuntime runtime) @@ -67,6 +68,7 @@ public void BuildApplicationWithAssetPackThatHasInvalidName (bool isRelease, And [Category ("SmokeTests")] [TestCase (false, AndroidRuntime.MonoVM)] [TestCase (true, AndroidRuntime.MonoVM)] + [TestCase (false, AndroidRuntime.CoreCLR)] [TestCase (true, AndroidRuntime.CoreCLR)] [TestCase (true, AndroidRuntime.NativeAOT)] public void BuildApplicationWithAssetPackOutsideProjectDirectory (bool isRelease, AndroidRuntime runtime) @@ -117,6 +119,7 @@ public void BuildApplicationWithAssetPackOutsideProjectDirectory (bool isRelease [Category ("SmokeTests")] [TestCase (false, AndroidRuntime.MonoVM)] [TestCase (true, AndroidRuntime.MonoVM)] + [TestCase (false, AndroidRuntime.CoreCLR)] [TestCase (true, AndroidRuntime.CoreCLR)] [TestCase (true, AndroidRuntime.NativeAOT)] public void BuildApplicationWithAssetPackOverrides (bool isRelease, AndroidRuntime runtime) @@ -160,6 +163,7 @@ public void BuildApplicationWithAssetPackOverrides (bool isRelease, AndroidRunti [Category ("SmokeTests")] [TestCase (false, AndroidRuntime.MonoVM)] [TestCase (true, AndroidRuntime.MonoVM)] + [TestCase (false, AndroidRuntime.CoreCLR)] [TestCase (true, AndroidRuntime.CoreCLR)] [TestCase (true, AndroidRuntime.NativeAOT)] public void BuildApplicationWithAssetPack (bool isRelease, AndroidRuntime runtime) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.TestCaseSource.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.TestCaseSource.cs index a7f5cf2fc49..593d68009cd 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.TestCaseSource.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.TestCaseSource.cs @@ -132,6 +132,13 @@ public partial class BuildTest : BaseTest /* usesAssemblyStore */ true, /* runtime */ AndroidRuntime.CoreCLR, }, + new object [] { + /* runtimeIdentifiers */ "android-arm64", + /* isRelease */ false, + /* aot */ false, + /* usesAssemblyStore */ true, + /* runtime */ AndroidRuntime.CoreCLR, + }, new object [] { /* runtimeIdentifiers */ "android-arm64", /* isRelease */ true, From c038e2f0f3845ee4ce737904669f331d3199d28c Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Thu, 8 May 2025 21:51:47 +0200 Subject: [PATCH 14/14] Use better looking code --- .../TypeMappingDebugNativeAssemblyGeneratorCLR.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/TypeMappingDebugNativeAssemblyGeneratorCLR.cs b/src/Xamarin.Android.Build.Tasks/Utilities/TypeMappingDebugNativeAssemblyGeneratorCLR.cs index 63506cdb4bd..2257754a2d5 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/TypeMappingDebugNativeAssemblyGeneratorCLR.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/TypeMappingDebugNativeAssemblyGeneratorCLR.cs @@ -22,12 +22,11 @@ sealed class TypeMapContextDataProvider : NativeAssemblerStructContextDataProvid public override ulong GetBufferSize (object data, string fieldName) { var map_module = EnsureType (data); - if (String.Compare ("java_to_managed", fieldName, StringComparison.Ordinal) == 0 || - String.Compare ("managed_to_java", fieldName, StringComparison.Ordinal) == 0) { - return map_module.entry_count; - } - - return 0; + return fieldName switch { + "java_to_managed" => map_module.entry_count, + "managed_to_java" => map_module.entry_count, + _ => 0 + }; } public override string? GetPointedToSymbolName (object data, string fieldName)