From 8706310f33df4aaeffce1c24c3650fb94dc5a3e0 Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Thu, 7 Feb 2019 04:34:48 +0100 Subject: [PATCH] Implement ManifestBasedResourceGroveler::GetNeutralResourcesLanguageAttribute (dotnet/coreclr#22372) * Implement ManifestBasedResourceGroveler::GetNeutralResourcesLanguageAttribute in shared managed code * Remove native ::GetNeutralResourcesLanguage Commit migrated from https://github.com/dotnet/coreclr/commit/ca432e07ad9b187931da13fd63f4f5d2fd513d5e --- .../ManifestBasedResourceGroveler.CoreCLR.cs | 13 ---- src/coreclr/src/debug/daccess/nidump.cpp | 1 - src/coreclr/src/vm/assemblynative.cpp | 32 -------- src/coreclr/src/vm/assemblynative.hpp | 3 - src/coreclr/src/vm/ceeload.cpp | 87 ---------------------- src/coreclr/src/vm/ceeload.h | 13 ---- src/coreclr/src/vm/ecalllist.h | 5 -- .../Resources/ManifestBasedResourceGroveler.cs | 29 ++++---- .../src/System/Resources/ResourceManager.cs | 8 +- 9 files changed, 15 insertions(+), 176 deletions(-) diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Resources/ManifestBasedResourceGroveler.CoreCLR.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Resources/ManifestBasedResourceGroveler.CoreCLR.cs index 44803d9..8791865 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Resources/ManifestBasedResourceGroveler.CoreCLR.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Resources/ManifestBasedResourceGroveler.CoreCLR.cs @@ -4,8 +4,6 @@ using System.Globalization; using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; namespace System.Resources { @@ -18,16 +16,5 @@ namespace System.Resources { return ((RuntimeAssembly)mainAssembly).InternalGetSatelliteAssembly(culture, version, throwOnFileNotFound: false); } - - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool GetNeutralResourcesLanguageAttribute(RuntimeAssembly assemblyHandle, StringHandleOnStack cultureName, out short fallbackLocation); - - private static bool GetNeutralResourcesLanguageAttribute(Assembly assemblyHandle, ref string cultureName, out short fallbackLocation) - { - return GetNeutralResourcesLanguageAttribute(((RuntimeAssembly)assemblyHandle).GetNativeHandle(), - JitHelpers.GetStringHandleOnStack(ref cultureName), - out fallbackLocation); - } } } diff --git a/src/coreclr/src/debug/daccess/nidump.cpp b/src/coreclr/src/debug/daccess/nidump.cpp index 2165e3e..9886aad 100644 --- a/src/coreclr/src/debug/daccess/nidump.cpp +++ b/src/coreclr/src/debug/daccess/nidump.cpp @@ -3647,7 +3647,6 @@ NativeImageDumper::EnumMnemonics NativeImageDumper::s_ModulePersistedFlags[] = MPF_ENTRY(DEFAULT_DLL_IMPORT_SEARCH_PATHS_IS_CACHED), MPF_ENTRY(DEFAULT_DLL_IMPORT_SEARCH_PATHS_STATUS), - MPF_ENTRY(NEUTRAL_RESOURCES_LANGUAGE_IS_CACHED), MPF_ENTRY(COMPUTED_METHODDEF_TO_PROPERTYINFO_MAP), MPF_ENTRY(LOW_LEVEL_SYSTEM_ASSEMBLY_BY_NAME), #undef MPF_ENTRY diff --git a/src/coreclr/src/vm/assemblynative.cpp b/src/coreclr/src/vm/assemblynative.cpp index 6a8efff..10e6319 100644 --- a/src/coreclr/src/vm/assemblynative.cpp +++ b/src/coreclr/src/vm/assemblynative.cpp @@ -679,38 +679,6 @@ void QCALLTYPE AssemblyNative::GetModules(QCall::AssemblyHandle pAssembly, BOOL END_QCALL; } -BOOL QCALLTYPE AssemblyNative::GetNeutralResourcesLanguageAttribute(QCall::AssemblyHandle pAssembly, QCall::StringHandleOnStack cultureName, INT16& outFallbackLocation) -{ - CONTRACTL { - QCALL_CHECK; - } CONTRACTL_END; - - BOOL retVal = FALSE; - BEGIN_QCALL; - - _ASSERTE(pAssembly); - Assembly * pAsm = pAssembly->GetAssembly(); - _ASSERTE(pAsm); - Module * pModule = pAsm->GetManifestModule(); - _ASSERTE(pModule); - - LPCUTF8 pszCultureName = NULL; - ULONG cultureNameLength = 0; - INT16 fallbackLocation = 0; - - // find the attribute if it exists - if (pModule->GetNeutralResourcesLanguage(&pszCultureName, &cultureNameLength, &fallbackLocation, FALSE)) { - StackSString culture(SString::Utf8, pszCultureName, cultureNameLength); - cultureName.Set(culture); - outFallbackLocation = fallbackLocation; - retVal = TRUE; - } - - END_QCALL; - - return retVal; -} - BOOL QCALLTYPE AssemblyNative::GetIsCollectible(QCall::AssemblyHandle pAssembly) { QCALL_CONTRACT; diff --git a/src/coreclr/src/vm/assemblynative.hpp b/src/coreclr/src/vm/assemblynative.hpp index 3ef7b0b..ca78c2d 100644 --- a/src/coreclr/src/vm/assemblynative.hpp +++ b/src/coreclr/src/vm/assemblynative.hpp @@ -72,9 +72,6 @@ public: static BYTE * QCALLTYPE GetResource(QCall::AssemblyHandle pAssembly, LPCWSTR wszName, DWORD * length); - static - BOOL QCALLTYPE GetNeutralResourcesLanguageAttribute(QCall::AssemblyHandle pAssembly, QCall::StringHandleOnStack cultureName, INT16& outFallbackLocation); - static FCDECL1(FC_BOOL_RET, IsDynamic, AssemblyBaseObject * pAssemblyUNSAFE); diff --git a/src/coreclr/src/vm/ceeload.cpp b/src/coreclr/src/vm/ceeload.cpp index d824a14..916cae6 100644 --- a/src/coreclr/src/vm/ceeload.cpp +++ b/src/coreclr/src/vm/ceeload.cpp @@ -2577,79 +2577,6 @@ BOOL Module::IsNoStringInterning() return !!(m_dwPersistedFlags & NO_STRING_INTERNING); } -BOOL Module::GetNeutralResourcesLanguage(LPCUTF8 * cultureName, ULONG * cultureNameLength, INT16 * fallbackLocation, BOOL cacheAttribute) -{ - STANDARD_VM_CONTRACT; - - BOOL retVal = FALSE; - if (!(m_dwPersistedFlags & NEUTRAL_RESOURCES_LANGUAGE_IS_CACHED)) - { - const BYTE *pVal = NULL; - ULONG cbVal = 0; - - // This flag applies to assembly, but it is stored on module so it can be cached in ngen image - // Thus, we should ever need it for manifest module only. - IMDInternalImport *mdImport = GetAssembly()->GetManifestImport(); - _ASSERTE(mdImport); - - mdToken token; - IfFailThrow(mdImport->GetAssemblyFromScope(&token)); - - // Check for the existance of the attribute. - HRESULT hr = mdImport->GetCustomAttributeByName(token,"System.Resources.NeutralResourcesLanguageAttribute",(const void **)&pVal, &cbVal); - if (hr == S_OK) { - - // we should not have a native image (it would have been cached at ngen time) - _ASSERTE(!HasNativeImage()); - - CustomAttributeParser cap(pVal, cbVal); - IfFailThrow(cap.SkipProlog()); - IfFailThrow(cap.GetString(cultureName, cultureNameLength)); - IfFailThrow(cap.GetI2(fallbackLocation)); - // Should only be true on Module.Save(). Update flag to show we have the attribute cached - if (cacheAttribute) - FastInterlockOr(&m_dwPersistedFlags, NEUTRAL_RESOURCES_LANGUAGE_IS_CACHED); - - retVal = TRUE; - } - } - else - { - *cultureName = m_pszCultureName; - *cultureNameLength = m_CultureNameLength; - *fallbackLocation = m_FallbackLocation; - retVal = TRUE; - -#ifdef _DEBUG - // confirm that the NGENed attribute is correct - LPCUTF8 pszCultureNameCheck = NULL; - ULONG cultureNameLengthCheck = 0; - INT16 fallbackLocationCheck = 0; - const BYTE *pVal = NULL; - ULONG cbVal = 0; - - IMDInternalImport *mdImport = GetAssembly()->GetManifestImport(); - _ASSERTE(mdImport); - mdToken token; - IfFailThrow(mdImport->GetAssemblyFromScope(&token)); - - // Confirm that the attribute exists, and has the save value as when we ngen'd it - HRESULT hr = mdImport->GetCustomAttributeByName(token,"System.Resources.NeutralResourcesLanguageAttribute",(const void **)&pVal, &cbVal); - _ASSERTE(hr == S_OK); - CustomAttributeParser cap(pVal, cbVal); - IfFailThrow(cap.SkipProlog()); - IfFailThrow(cap.GetString(&pszCultureNameCheck, &cultureNameLengthCheck)); - IfFailThrow(cap.GetI2(&fallbackLocationCheck)); - _ASSERTE(cultureNameLengthCheck == m_CultureNameLength); - _ASSERTE(fallbackLocationCheck == m_FallbackLocation); - _ASSERTE(strncmp(pszCultureNameCheck,m_pszCultureName,m_CultureNameLength) == 0); -#endif // _DEBUG - } - - return retVal; -} - - BOOL Module::HasDefaultDllImportSearchPathsAttribute() { CONTRACTL @@ -8540,15 +8467,6 @@ void Module::Save(DataImage *image) // CorProfileData * profileData = GetProfileData(); - // ngen the neutral resources culture - if(GetNeutralResourcesLanguage(&m_pszCultureName, &m_CultureNameLength, &m_FallbackLocation, TRUE)) { - image->StoreStructure((void *) m_pszCultureName, - (ULONG)(m_CultureNameLength + 1), - DataImage::ITEM_BINDER_ITEMS, - 1); - } - - m_TypeRefToMethodTableMap.Save(image, DataImage::ITEM_TYPEREF_MAP, profileData, mdtTypeRef); image->BindPointer(&m_TypeRefToMethodTableMap, pModuleNode, offsetof(Module, m_TypeRefToMethodTableMap)); @@ -9604,11 +9522,6 @@ void Module::Fixup(DataImage *image) image->ZeroPointerField(this, offsetof(Module, m_pNgenStats)); - // fixup the pointer for NeutralResourcesLanguage, if we have it cached - if(!!(m_dwPersistedFlags & NEUTRAL_RESOURCES_LANGUAGE_IS_CACHED)) { - image->FixupPointerField(this, offsetof(Module, m_pszCultureName)); - } - // Fixup the property name set image->FixupPointerField(this, offsetof(Module, m_propertyNameSet)); diff --git a/src/coreclr/src/vm/ceeload.h b/src/coreclr/src/vm/ceeload.h index aa0b789..6bf5fbd 100644 --- a/src/coreclr/src/vm/ceeload.h +++ b/src/coreclr/src/vm/ceeload.h @@ -1407,9 +1407,6 @@ private: //If module has default dll import search paths attribute DEFAULT_DLL_IMPORT_SEARCH_PATHS_STATUS = 0x00000800, - //If attribute value has been cached before - NEUTRAL_RESOURCES_LANGUAGE_IS_CACHED = 0x00001000, - //If m_MethodDefToPropertyInfoMap has been generated COMPUTED_METHODDEF_TO_PROPERTYINFO_MAP = 0x00002000, @@ -1518,10 +1515,6 @@ private: ULONG m_DefaultDllImportSearchPathsAttributeValue; - LPCUTF8 m_pszCultureName; - ULONG m_CultureNameLength; - INT16 m_FallbackLocation; - #ifdef PROFILING_SUPPORTED_DATA // a wrapper for the underlying PEFile metadata emitter which validates that the metadata edits being // made are supported modifications to the type system @@ -3176,12 +3169,6 @@ public: //----------------------------------------------------------------------------------------- BOOL IsPreV4Assembly(); - - //----------------------------------------------------------------------------------------- - // Parse/Return NeutralResourcesLanguageAttribute if it exists (updates Module member variables at ngen time) - //----------------------------------------------------------------------------------------- - BOOL GetNeutralResourcesLanguage(LPCUTF8 * cultureName, ULONG * cultureNameLength, INT16 * fallbackLocation, BOOL cacheAttribute); - protected: diff --git a/src/coreclr/src/vm/ecalllist.h b/src/coreclr/src/vm/ecalllist.h index 9a1d692..c604db3 100644 --- a/src/coreclr/src/vm/ecalllist.h +++ b/src/coreclr/src/vm/ecalllist.h @@ -479,10 +479,6 @@ FCFuncStart(gTypeNameParser) QCFuncElement("_GetAssemblyName", TypeName::QGetAssemblyName) FCFuncEnd() -FCFuncStart(gManifestBasedResourceGrovelerFuncs) - QCFuncElement("GetNeutralResourcesLanguageAttribute", AssemblyNative::GetNeutralResourcesLanguageAttribute) -FCFuncEnd() - FCFuncStart(gRuntimeAssemblyFuncs) QCFuncElement("GetFullName", AssemblyNative::GetFullName) QCFuncElement("GetLocation", AssemblyNative::GetLocation) @@ -1237,7 +1233,6 @@ FCClassElement("InterfaceMarshaler", "System.StubHelpers", gInterfaceMarshalerFu #endif FCClassElement("Interlocked", "System.Threading", gInterlockedFuncs) FCClassElement("LoaderAllocatorScout", "System.Reflection", gLoaderAllocatorFuncs) -FCClassElement("ManifestBasedResourceGroveler", "System.Resources", gManifestBasedResourceGrovelerFuncs) FCClassElement("Marshal", "System.Runtime.InteropServices", gInteropMarshalFuncs) FCClassElement("Math", "System", gMathFuncs) FCClassElement("MathF", "System", gMathFFuncs) diff --git a/src/libraries/System.Private.CoreLib/src/System/Resources/ManifestBasedResourceGroveler.cs b/src/libraries/System.Private.CoreLib/src/System/Resources/ManifestBasedResourceGroveler.cs index 79fd856..d7b3726 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Resources/ManifestBasedResourceGroveler.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Resources/ManifestBasedResourceGroveler.cs @@ -140,29 +140,26 @@ namespace System.Resources return returnCulture; } - internal static CultureInfo GetNeutralResourcesLanguage(Assembly a, ref UltimateResourceFallbackLocation fallbackLocation) + internal static CultureInfo GetNeutralResourcesLanguage(Assembly a, out UltimateResourceFallbackLocation fallbackLocation) { Debug.Assert(a != null, "assembly != null"); - string cultureName = null; - short fallback = 0; - if (GetNeutralResourcesLanguageAttribute(a, ref cultureName, out fallback)) - { - if ((UltimateResourceFallbackLocation)fallback < UltimateResourceFallbackLocation.MainAssembly || (UltimateResourceFallbackLocation)fallback > UltimateResourceFallbackLocation.Satellite) - { - throw new ArgumentException(SR.Format(SR.Arg_InvalidNeutralResourcesLanguage_FallbackLoc, fallback)); - } - fallbackLocation = (UltimateResourceFallbackLocation)fallback; - } - else + + var attr = a.GetCustomAttribute(); + if (attr == null) { fallbackLocation = UltimateResourceFallbackLocation.MainAssembly; return CultureInfo.InvariantCulture; } + fallbackLocation = attr.Location; + if (fallbackLocation < UltimateResourceFallbackLocation.MainAssembly || fallbackLocation > UltimateResourceFallbackLocation.Satellite) + { + throw new ArgumentException(SR.Format(SR.Arg_InvalidNeutralResourcesLanguage_FallbackLoc, fallbackLocation)); + } + try { - CultureInfo c = CultureInfo.GetCultureInfo(cultureName); - return c; + return CultureInfo.GetCultureInfo(attr.CultureName); } catch (ArgumentException e) { // we should catch ArgumentException only. @@ -171,11 +168,11 @@ namespace System.Resources // fires, please fix the build process for the BCL directory. if (a == typeof(object).Assembly) { - Debug.Fail(System.CoreLib.Name + "'s NeutralResourcesLanguageAttribute is a malformed culture name! name: \"" + cultureName + "\" Exception: " + e); + Debug.Fail(System.CoreLib.Name + "'s NeutralResourcesLanguageAttribute is a malformed culture name! name: \"" + attr.CultureName + "\" Exception: " + e); return CultureInfo.InvariantCulture; } - throw new ArgumentException(SR.Format(SR.Arg_InvalidNeutralResourcesLanguage_Asm_Culture, a.ToString(), cultureName), e); + throw new ArgumentException(SR.Format(SR.Arg_InvalidNeutralResourcesLanguage_Asm_Culture, a.ToString(), attr.CultureName), e); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Resources/ResourceManager.cs b/src/libraries/System.Private.CoreLib/src/System/Resources/ResourceManager.cs index f13afc1..7b0033c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Resources/ResourceManager.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Resources/ResourceManager.cs @@ -249,12 +249,10 @@ namespace System.Resources _resourceSets = new Dictionary(); _lastUsedResourceCache = new CultureNameResourceSetPair(); - _fallbackLoc = UltimateResourceFallbackLocation.MainAssembly; - ResourceManagerMediator mediator = new ResourceManagerMediator(this); _resourceGroveler = new ManifestBasedResourceGroveler(mediator); - _neutralResourcesCulture = ManifestBasedResourceGroveler.GetNeutralResourcesLanguage(MainAssembly, ref _fallbackLoc); + _neutralResourcesCulture = ManifestBasedResourceGroveler.GetNeutralResourcesLanguage(MainAssembly, out _fallbackLoc); } // Gets the base name for the ResourceManager. @@ -556,9 +554,7 @@ namespace System.Resources { // This method should be obsolete - replace it with the one below. // Unfortunately, we made it protected. - UltimateResourceFallbackLocation ignoringUsefulData = UltimateResourceFallbackLocation.MainAssembly; - CultureInfo culture = ManifestBasedResourceGroveler.GetNeutralResourcesLanguage(a, ref ignoringUsefulData); - return culture; + return ManifestBasedResourceGroveler.GetNeutralResourcesLanguage(a, out _); } // IGNORES VERSION -- 2.7.4