diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index a75171aeda1b0..e72c4bf950c2c 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -15,7 +15,7 @@ ] }, "microsoft.dotnet.xharness.cli": { - "version": "9.0.0-prerelease.24452.1", + "version": "10.0.0-prerelease.24459.1", "commands": [ "xharness" ] diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 77c06d86deee3..238887c6bd098 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -316,17 +316,17 @@ https://github.com/dotnet/runtime 7cb32e193a55a95c74fc3bd56501b951b48b700f - + https://github.com/dotnet/xharness - c2215b88cdac5390888de3e6ad301c113f40ed6c + df9b6509e6b3976d158e46c23d72d6acd9f0d326 - + https://github.com/dotnet/xharness - c2215b88cdac5390888de3e6ad301c113f40ed6c + df9b6509e6b3976d158e46c23d72d6acd9f0d326 - + https://github.com/dotnet/xharness - c2215b88cdac5390888de3e6ad301c113f40ed6c + df9b6509e6b3976d158e46c23d72d6acd9f0d326 https://github.com/dotnet/arcade diff --git a/eng/Versions.props b/eng/Versions.props index a6407d4ed6c89..44522b33fd4a5 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -180,9 +180,9 @@ 1.4.0 17.4.0-preview-20220707-01 - 9.0.0-prerelease.24452.1 - 9.0.0-prerelease.24452.1 - 9.0.0-prerelease.24452.1 + 10.0.0-prerelease.24459.1 + 10.0.0-prerelease.24459.1 + 10.0.0-prerelease.24459.1 9.0.0-alpha.0.24419.1 3.12.0 4.5.0 diff --git a/eng/pipelines/common/templates/runtimes/build-runtime-tests-and-send-to-helix.yml b/eng/pipelines/common/templates/runtimes/build-runtime-tests-and-send-to-helix.yml index a189770cb81be..2ac52ca77eb35 100644 --- a/eng/pipelines/common/templates/runtimes/build-runtime-tests-and-send-to-helix.yml +++ b/eng/pipelines/common/templates/runtimes/build-runtime-tests-and-send-to-helix.yml @@ -70,7 +70,7 @@ steps: displayName: "AOT compile CoreCLR tests" target: ${{ coalesce(parameters.llvmAotStepContainer, parameters.container) }} - ${{ if in(parameters.runtimeVariant, 'llvmfullaot', 'minifullaot') }}: - - script: $(Build.SourcesDirectory)/src/tests/build$(scriptExt) $(logRootNameArg)MonoAot mono_fullaot ${{ parameters.buildConfig }} ${{ parameters.archType }} /p:RuntimeVariant=${{ parameters.runtimeVariant }} -maxcpucount:2 + - script: $(Build.SourcesDirectory)/src/tests/build$(scriptExt) $(logRootNameArg)MonoAot mono_fullaot ${{ parameters.buildConfig }} ${{ parameters.archType }} /p:RuntimeVariant=${{ parameters.runtimeVariant }} -maxcpucount:1 displayName: "AOT compile CoreCLR tests" target: ${{ coalesce(parameters.llvmAotStepContainer, parameters.container) }} - ${{ if eq(parameters.archType, 'arm64') }}: diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs index ccd3d9aa9efc5..95bcf0652648a 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs @@ -115,8 +115,6 @@ public override string? CodeBase } } - internal RuntimeAssembly GetNativeHandle() => this; - // If the assembly is copied before it is loaded, the codebase will be set to the // actual file loaded if copiedName is true. If it is false, then the original code base // is returned. @@ -263,7 +261,7 @@ public override Type[] GetExportedTypes() public override IEnumerable DefinedTypes { [RequiresUnreferencedCode("Types might be removed")] - get => GetManifestModule(GetNativeHandle()).GetDefinedTypes(); + get => GetManifestModule().GetDefinedTypes(); } [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_GetIsCollectible")] @@ -324,7 +322,7 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont public override Module ManifestModule => // We don't need to return the "external" ModuleBuilder because // it is meant to be read-only - GetManifestModule(GetNativeHandle()); + GetManifestModule(); public override object[] GetCustomAttributes(bool inherit) { @@ -586,9 +584,17 @@ private CultureInfo GetLocale() } [MethodImpl(MethodImplOptions.InternalCall)] - private static extern bool FCallIsDynamic(RuntimeAssembly assembly); + private static extern bool GetIsDynamic(IntPtr assembly); - public override bool IsDynamic => FCallIsDynamic(GetNativeHandle()); + public override bool IsDynamic + { + get + { + bool isDynamic = GetIsDynamic(GetUnderlyingNativeHandle()); + GC.KeepAlive(this); // We directly pass the native handle above - make sure this object stays alive for the call + return isDynamic; + } + } [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_GetSimpleName")] private static partial void GetSimpleName(QCallAssembly assembly, StringHandleOnStack retSimpleName); @@ -701,8 +707,24 @@ public override Module[] GetLoadedModules(bool getResourceModules) return GetModulesInternal(false, getResourceModules); } + private RuntimeModule GetManifestModule() + { + return GetManifestModule(this) ?? GetManifestModuleWorker(this); + + [MethodImpl(MethodImplOptions.NoInlining)] + static RuntimeModule GetManifestModuleWorker(RuntimeAssembly assembly) + { + RuntimeModule? module = null; + GetManifestModuleSlow(ObjectHandleOnStack.Create(ref assembly), ObjectHandleOnStack.Create(ref module)); + return module!; + } + } + [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern RuntimeModule GetManifestModule(RuntimeAssembly assembly); + private static extern RuntimeModule? GetManifestModule(RuntimeAssembly assembly); + + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyHandle_GetManifestModuleSlow")] + private static partial void GetManifestModuleSlow(ObjectHandleOnStack assembly, ObjectHandleOnStack module); [MethodImpl(MethodImplOptions.InternalCall)] internal static extern int GetToken(RuntimeAssembly assembly); @@ -713,7 +735,7 @@ public sealed override Type[] GetForwardedTypes() List types = new List(); List exceptions = new List(); - MetadataImport scope = GetManifestModule(GetNativeHandle()).MetadataImport; + MetadataImport scope = GetManifestModule().MetadataImport; scope.Enum(MetadataTokenType.ExportedType, 0, out MetadataEnumResult enumResult); RuntimeAssembly runtimeAssembly = this; QCallAssembly pAssembly = new QCallAssembly(ref runtimeAssembly); diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs index a610a5cbe3eab..2ac866f246fce 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs @@ -82,7 +82,7 @@ internal static IList GetCustomAttributesInternal(RuntimeAs // No pseudo attributes for RuntimeAssembly - return GetCustomAttributes((RuntimeModule)target.ManifestModule, RuntimeAssembly.GetToken(target.GetNativeHandle())); + return GetCustomAttributes((RuntimeModule)target.ManifestModule, RuntimeAssembly.GetToken(target)); } internal static IList GetCustomAttributesInternal(RuntimeParameterInfo target) @@ -1227,7 +1227,7 @@ internal static bool IsDefined(RuntimeAssembly assembly, RuntimeType caType) Debug.Assert(caType is not null); // No pseudo attributes for RuntimeAssembly - return IsCustomAttributeDefined((assembly.ManifestModule as RuntimeModule)!, RuntimeAssembly.GetToken(assembly.GetNativeHandle()), caType); + return IsCustomAttributeDefined((assembly.ManifestModule as RuntimeModule)!, RuntimeAssembly.GetToken(assembly), caType); } internal static bool IsDefined(RuntimeModule module, RuntimeType caType) @@ -1388,7 +1388,7 @@ internal static object[] GetCustomAttributes(RuntimeAssembly assembly, RuntimeTy // No pseudo attributes for RuntimeAssembly - int assemblyToken = RuntimeAssembly.GetToken(assembly.GetNativeHandle()); + int assemblyToken = RuntimeAssembly.GetToken(assembly); return GetCustomAttributes((assembly.ManifestModule as RuntimeModule)!, assemblyToken, 0, caType); } diff --git a/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs b/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs index 3d230536519ce..d78cc1ea86bc1 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs @@ -306,11 +306,43 @@ internal RuntimeType GetRuntimeType() [MethodImpl(MethodImplOptions.InternalCall)] internal static extern CorElementType GetCorElementType(RuntimeType type); + internal static RuntimeAssembly GetAssembly(RuntimeType type) + { + return GetAssemblyIfExists(type) ?? GetAssemblyWorker(type); + + [MethodImpl(MethodImplOptions.NoInlining)] + static RuntimeAssembly GetAssemblyWorker(RuntimeType type) + { + RuntimeAssembly? assembly = null; + GetAssemblySlow(ObjectHandleOnStack.Create(ref type), ObjectHandleOnStack.Create(ref assembly)); + return assembly!; + } + } + [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern RuntimeAssembly GetAssembly(RuntimeType type); + private static extern RuntimeAssembly? GetAssemblyIfExists(RuntimeType type); + + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "RuntimeTypeHandle_GetAssemblySlow")] + private static partial void GetAssemblySlow(ObjectHandleOnStack type, ObjectHandleOnStack assembly); + + internal static RuntimeModule GetModule(RuntimeType type) + { + return GetModuleIfExists(type) ?? GetModuleWorker(type); + + [MethodImpl(MethodImplOptions.NoInlining)] + static RuntimeModule GetModuleWorker(RuntimeType type) + { + RuntimeModule? module = null; + GetModuleSlow(ObjectHandleOnStack.Create(ref type), ObjectHandleOnStack.Create(ref module)); + return module!; + } + } [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern RuntimeModule GetModule(RuntimeType type); + private static extern RuntimeModule? GetModuleIfExists(RuntimeType type); + + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "RuntimeTypeHandle_GetModuleSlow")] + private static partial void GetModuleSlow(ObjectHandleOnStack type, ObjectHandleOnStack module); public ModuleHandle GetModuleHandle() { diff --git a/src/coreclr/System.Private.CoreLib/src/System/Threading/LowLevelLifoSemaphore.Unix.cs b/src/coreclr/System.Private.CoreLib/src/System/Threading/LowLevelLifoSemaphore.Unix.cs index 8fe80e7286858..25fc6ff09ad2a 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Threading/LowLevelLifoSemaphore.Unix.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Threading/LowLevelLifoSemaphore.Unix.cs @@ -31,7 +31,7 @@ public bool WaitCore(int timeoutMs) return waitResult == WaitHandle.WaitSuccess; } - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "WaitHandle_CorWaitOnePrioritizedNative")] + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "WaitHandle_WaitOnePrioritized")] private static partial int WaitNative(SafeWaitHandle handle, int timeoutMs); private void ReleaseCore(int count) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Threading/Thread.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Threading/Thread.CoreCLR.cs index 486e5a505abeb..08b3ae8944d63 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Threading/Thread.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Threading/Thread.CoreCLR.cs @@ -151,13 +151,24 @@ public static void SpinWait(int iterations) public static bool Yield() => YieldInternal() != Interop.BOOL.FALSE; [MethodImpl(MethodImplOptions.NoInlining)] - private static Thread InitializeCurrentThread() => t_currentThread = GetCurrentThreadNative(); + private static Thread InitializeCurrentThread() + { + Thread? thread = null; + GetCurrentThread(ObjectHandleOnStack.Create(ref thread)); + return t_currentThread = thread!; + } - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern Thread GetCurrentThreadNative(); + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ThreadNative_GetCurrentThread")] + private static partial void GetCurrentThread(ObjectHandleOnStack thread); - [MethodImpl(MethodImplOptions.InternalCall)] - private extern void Initialize(); + private void Initialize() + { + Thread _this = this; + Initialize(ObjectHandleOnStack.Create(ref _this)); + } + + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ThreadNative_Initialize")] + private static partial void Initialize(ObjectHandleOnStack thread); /// Clean up the thread when it goes away. ~Thread() => InternalFinalize(); // Delegate to the unmanaged portion. @@ -175,11 +186,7 @@ partial void ThreadNameChanged(string? value) private static partial void InformThreadNameChange(ThreadHandle t, string? name, int len); /// Returns true if the thread has been started and is not dead. - public extern bool IsAlive - { - [MethodImpl(MethodImplOptions.InternalCall)] - get; - } + public bool IsAlive => (ThreadState & (ThreadState.Unstarted | ThreadState.Stopped | ThreadState.Aborted)) == 0; /// /// Return whether or not this thread is a background thread. Background @@ -247,10 +254,19 @@ public ThreadPriority Priority /// Return the thread state as a consistent set of bits. This is more /// general then IsAlive or IsBackground. /// - public ThreadState ThreadState => (ThreadState)GetThreadStateNative(); + public ThreadState ThreadState + { + get + { + var state = (ThreadState)GetThreadState(GetNativeHandle()); + GC.KeepAlive(this); + return state; + } + } - [MethodImpl(MethodImplOptions.InternalCall)] - private extern int GetThreadStateNative(); + [SuppressGCTransition] + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ThreadNative_GetThreadState")] + private static partial int GetThreadState(ThreadHandle t); /// /// An unstarted thread can be marked to indicate that it will host a @@ -327,6 +343,7 @@ public void DisableComObjectEagerCleanup() GC.KeepAlive(this); } + [SuppressGCTransition] [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ThreadNative_DisableComObjectEagerCleanup")] private static partial void DisableComObjectEagerCleanup(ThreadHandle t); #else // !FEATURE_COMINTEROP diff --git a/src/coreclr/System.Private.CoreLib/src/System/Threading/WaitHandle.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Threading/WaitHandle.CoreCLR.cs index f1bfe33e8c8bc..a9fc4d8b2a045 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Threading/WaitHandle.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Threading/WaitHandle.CoreCLR.cs @@ -8,23 +8,18 @@ namespace System.Threading { public abstract partial class WaitHandle { - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern int WaitOneCore(IntPtr waitHandle, int millisecondsTimeout, bool useTrivialWaits); + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "WaitHandle_WaitOneCore")] + private static partial int WaitOneCore(IntPtr waitHandle, int millisecondsTimeout, [MarshalAs(UnmanagedType.Bool)] bool useTrivialWaits); private static unsafe int WaitMultipleIgnoringSyncContextCore(ReadOnlySpan waitHandles, bool waitAll, int millisecondsTimeout) - { - fixed (IntPtr* pWaitHandles = &MemoryMarshal.GetReference(waitHandles)) - { - return WaitMultipleIgnoringSyncContext(pWaitHandles, waitHandles.Length, waitAll, millisecondsTimeout); - } - } + => WaitMultipleIgnoringSyncContext(waitHandles, waitHandles.Length, waitAll, millisecondsTimeout); - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern unsafe int WaitMultipleIgnoringSyncContext(IntPtr* waitHandles, int numHandles, bool waitAll, int millisecondsTimeout); + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "WaitHandle_WaitMultipleIgnoringSyncContext")] + private static partial int WaitMultipleIgnoringSyncContext(ReadOnlySpan waitHandles, int numHandles, [MarshalAs(UnmanagedType.Bool)] bool waitAll, int millisecondsTimeout); private static int SignalAndWaitCore(IntPtr waitHandleToSignal, IntPtr waitHandleToWaitOn, int millisecondsTimeout) { - int ret = SignalAndWaitNative(waitHandleToSignal, waitHandleToWaitOn, millisecondsTimeout); + int ret = SignalAndWait(waitHandleToSignal, waitHandleToWaitOn, millisecondsTimeout); if (ret == Interop.Errors.ERROR_TOO_MANY_POSTS) { @@ -34,7 +29,7 @@ private static int SignalAndWaitCore(IntPtr waitHandleToSignal, IntPtr waitHandl return ret; } - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern int SignalAndWaitNative(IntPtr waitHandleToSignal, IntPtr waitHandleToWaitOn, int millisecondsTimeout); + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "WaitHandle_SignalAndWait")] + private static partial int SignalAndWait(IntPtr waitHandleToSignal, IntPtr waitHandleToWaitOn, int millisecondsTimeout); } } diff --git a/src/coreclr/debug/daccess/dacdbiimpl.cpp b/src/coreclr/debug/daccess/dacdbiimpl.cpp index 6309533648bb2..223d675df254a 100644 --- a/src/coreclr/debug/daccess/dacdbiimpl.cpp +++ b/src/coreclr/debug/daccess/dacdbiimpl.cpp @@ -5557,6 +5557,8 @@ CorDebugUserState DacDbiInterfaceImpl::GetPartialUserState(VMPTR_Thread vmThread result |= USER_STOPPED; } + // Don't report Thread::TS_AbortRequested + // The interruptible flag is unreliable (see issue 699245) // The Debugger_SleepWaitJoin is always accurate when it is present, but it is still // just a band-aid fix to cover some of the race conditions interruptible has. diff --git a/src/coreclr/debug/daccess/dacimpl.h b/src/coreclr/debug/daccess/dacimpl.h index 0d3ab3ad7bd18..cec666bc02bc1 100644 --- a/src/coreclr/debug/daccess/dacimpl.h +++ b/src/coreclr/debug/daccess/dacimpl.h @@ -1061,7 +1061,7 @@ class ClrDataAccess virtual HRESULT STDMETHODCALLTYPE GetAppDomainData(CLRDATA_ADDRESS addr, struct DacpAppDomainData *data); virtual HRESULT STDMETHODCALLTYPE GetAppDomainName(CLRDATA_ADDRESS addr, unsigned int count, _Inout_updates_z_(count) WCHAR *name, unsigned int *pNeeded); virtual HRESULT STDMETHODCALLTYPE GetAssemblyList(CLRDATA_ADDRESS appDomain, int count, CLRDATA_ADDRESS values[], int *fetched); - virtual HRESULT STDMETHODCALLTYPE GetAssemblyData(CLRDATA_ADDRESS baseDomainPtr, CLRDATA_ADDRESS assembly, struct DacpAssemblyData *data); + virtual HRESULT STDMETHODCALLTYPE GetAssemblyData(CLRDATA_ADDRESS domainPtr, CLRDATA_ADDRESS assembly, struct DacpAssemblyData *data); virtual HRESULT STDMETHODCALLTYPE GetAssemblyName(CLRDATA_ADDRESS assembly, unsigned int count, _Inout_updates_z_(count) WCHAR *name, unsigned int *pNeeded); virtual HRESULT STDMETHODCALLTYPE GetThreadData(CLRDATA_ADDRESS thread, struct DacpThreadData *data); virtual HRESULT STDMETHODCALLTYPE GetThreadFromThinlockID(UINT thinLockId, CLRDATA_ADDRESS *pThread); diff --git a/src/coreclr/debug/daccess/request.cpp b/src/coreclr/debug/daccess/request.cpp index 2be13b91e98aa..5e73d02325112 100644 --- a/src/coreclr/debug/daccess/request.cpp +++ b/src/coreclr/debug/daccess/request.cpp @@ -2834,19 +2834,17 @@ ClrDataAccess::GetAppDomainData(CLRDATA_ADDRESS addr, struct DacpAppDomainData * } else { - PTR_BaseDomain pBaseDomain = PTR_BaseDomain(TO_TADDR(addr)); - ZeroMemory(appdomainData, sizeof(DacpAppDomainData)); - appdomainData->AppDomainPtr = PTR_CDADDR(pBaseDomain); + appdomainData->AppDomainPtr = addr; PTR_LoaderAllocator pLoaderAllocator = SystemDomain::GetGlobalLoaderAllocator(); appdomainData->pHighFrequencyHeap = HOST_CDADDR(pLoaderAllocator->GetHighFrequencyHeap()); appdomainData->pLowFrequencyHeap = HOST_CDADDR(pLoaderAllocator->GetLowFrequencyHeap()); appdomainData->pStubHeap = HOST_CDADDR(pLoaderAllocator->GetStubHeap()); appdomainData->appDomainStage = STAGE_OPEN; - if (pBaseDomain->IsAppDomain()) + if (addr != HOST_CDADDR(SystemDomain::System())) { - AppDomain * pAppDomain = pBaseDomain->AsAppDomain(); + PTR_AppDomain pAppDomain = PTR_AppDomain(TO_TADDR(addr)); appdomainData->DomainLocalBlock = 0; appdomainData->pDomainLocalModules = 0; @@ -2963,15 +2961,19 @@ ClrDataAccess::GetAssemblyList(CLRDATA_ADDRESS addr, int count, CLRDATA_ADDRESS SOSDacEnter(); - BaseDomain* pBaseDomain = PTR_BaseDomain(TO_TADDR(addr)); - - int n=0; - if (pBaseDomain->IsAppDomain()) + if (addr == HOST_CDADDR(SystemDomain::System())) + { + // We shouldn't be asking for the assemblies in SystemDomain + hr = E_INVALIDARG; + } + else { - AppDomain::AssemblyIterator i = pBaseDomain->AsAppDomain()->IterateAssembliesEx( + PTR_AppDomain pAppDomain = PTR_AppDomain(TO_TADDR(addr)); + AppDomain::AssemblyIterator i = pAppDomain->IterateAssembliesEx( (AssemblyIterationFlags)(kIncludeLoading | kIncludeLoaded | kIncludeExecution)); CollectibleAssemblyHolder pDomainAssembly; + int n = 0; if (values) { while (i.Next(pDomainAssembly.This()) && (n < count)) @@ -2994,13 +2996,6 @@ ClrDataAccess::GetAssemblyList(CLRDATA_ADDRESS addr, int count, CLRDATA_ADDRESS if (pNeeded) *pNeeded = n; } - else - { - // The only other type of BaseDomain is the SystemDomain, and we shouldn't be asking - // for the assemblies in it. - _ASSERTE(false); - hr = E_INVALIDARG; - } SOSDacLeave(); return hr; @@ -3040,10 +3035,9 @@ ClrDataAccess::GetAppDomainName(CLRDATA_ADDRESS addr, unsigned int count, _Inout { SOSDacEnter(); - PTR_BaseDomain pBaseDomain = PTR_BaseDomain(TO_TADDR(addr)); - if (!pBaseDomain->IsAppDomain()) + if (addr == HOST_CDADDR(SystemDomain::System())) { - // Shared domain and SystemDomain don't have this field. + // SystemDomain doesn't have this field. if (pNeeded) *pNeeded = 1; if (name) @@ -3051,8 +3045,7 @@ ClrDataAccess::GetAppDomainName(CLRDATA_ADDRESS addr, unsigned int count, _Inout } else { - AppDomain* pAppDomain = pBaseDomain->AsAppDomain(); - + PTR_AppDomain pAppDomain = PTR_AppDomain(TO_TADDR(addr)); if (!pAppDomain->m_friendlyName.IsEmpty()) { if (!pAppDomain->m_friendlyName.DacGetUnicode(count, name, pNeeded)) @@ -3103,9 +3096,9 @@ ClrDataAccess::GetAppDomainConfigFile(CLRDATA_ADDRESS appDomain, int count, } HRESULT -ClrDataAccess::GetAssemblyData(CLRDATA_ADDRESS cdBaseDomainPtr, CLRDATA_ADDRESS assembly, struct DacpAssemblyData *assemblyData) +ClrDataAccess::GetAssemblyData(CLRDATA_ADDRESS domain, CLRDATA_ADDRESS assembly, struct DacpAssemblyData *assemblyData) { - if (assembly == (CLRDATA_ADDRESS)NULL && cdBaseDomainPtr == (CLRDATA_ADDRESS)NULL) + if (assembly == (CLRDATA_ADDRESS)NULL && domain == (CLRDATA_ADDRESS)NULL) { return E_INVALIDARG; } @@ -3117,14 +3110,9 @@ ClrDataAccess::GetAssemblyData(CLRDATA_ADDRESS cdBaseDomainPtr, CLRDATA_ADDRESS // Make sure conditionally-assigned fields like AssemblySecDesc, LoadContext, etc. are zeroed ZeroMemory(assemblyData, sizeof(DacpAssemblyData)); - // If the specified BaseDomain is an AppDomain, get a pointer to it - AppDomain * pDomain = NULL; - if (cdBaseDomainPtr != (CLRDATA_ADDRESS)NULL) + if (domain != (CLRDATA_ADDRESS)NULL) { - assemblyData->BaseDomainPtr = cdBaseDomainPtr; - PTR_BaseDomain baseDomain = PTR_BaseDomain(TO_TADDR(cdBaseDomainPtr)); - if( baseDomain->IsAppDomain() ) - pDomain = baseDomain->AsAppDomain(); + assemblyData->DomainPtr = domain; } assemblyData->AssemblyPtr = HOST_CDADDR(pAssembly); diff --git a/src/coreclr/debug/di/process.cpp b/src/coreclr/debug/di/process.cpp index aae787486adbc..fffd6df484825 100644 --- a/src/coreclr/debug/di/process.cpp +++ b/src/coreclr/debug/di/process.cpp @@ -11157,17 +11157,49 @@ void CordbProcess::HandleSetThreadContextNeeded(DWORD dwThreadId) LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded\n")); #if defined(TARGET_WINDOWS) && defined(TARGET_AMD64) - HandleHolder hThread = OpenThread( - THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_QUERY_INFORMATION | THREAD_SUSPEND_RESUME, - FALSE, // thread handle is not inheritable. - dwThreadId); + // Before we can read the left side context information, we must: + // 1. obtain the thread handle + // 2. suspened the thread + // 3. read the thread context, and from that read the pointer to the left-side context and the size of the context + // 4. then we can perform the actual SetThreadContext operation + // 5. lastly, we must resume the thread + // For the first step of obtaining the thread handle, + // we have previously attempted to use ::OpenThread to get a handle to the thread. + // However, there are situations where OpenThread can fail with an Access Denied error. + // From https://github.com/dotnet/runtime/issues/107263, the control-c handler in + // Windows causes the process to have higher privileges. + // We are now using the following approach to access the thread handle, which is the same + // approach used by CordbThread::RefreshHandle: + // 1. Get the thread handle from the DAC + // 2. Duplicate the handle to the current process + + // lookup the CordbThread by thread ID, so that we can access the left-side thread handle + CordbThread * pThread = TryLookupOrCreateThreadByVolatileOSId(dwThreadId); + + IDacDbiInterface* pDAC = GetDAC(); + if (pDAC == NULL) + { + LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - DAC not initialized\n")); + ThrowHR(E_UNEXPECTED); + } - if (hThread == NULL) + HANDLE hOutOfProcThread = pDAC->GetThreadHandle(pThread->m_vmThreadToken); + if (hOutOfProcThread == NULL) { - LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - Unexpected result from OpenThread\n")); + LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - Failed to get thread handle\n")); ThrowHR(E_UNEXPECTED); } + // Duplicate the thread handle to the current process + HandleHolder hThread; + BOOL fSuccess = DuplicateHandle(UnsafeGetProcessHandle(), hOutOfProcThread, ::GetCurrentProcess(), &hThread, 0, FALSE, DUPLICATE_SAME_ACCESS); + if (!fSuccess) + { + LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - Unexpected result from DuplicateHandle\n")); + ThrowHR(HRESULT_FROM_GetLastError()); + } + + // Suspend the thread and so that we can read the thread context. DWORD previousSuspendCount = ::SuspendThread(hThread); if (previousSuspendCount == (DWORD)-1) { @@ -11178,12 +11210,22 @@ void CordbProcess::HandleSetThreadContextNeeded(DWORD dwThreadId) DT_CONTEXT context = { 0 }; context.ContextFlags = CONTEXT_FULL; - HRESULT hr = GetDataTarget()->GetThreadContext(dwThreadId, CONTEXT_FULL, sizeof(DT_CONTEXT), reinterpret_cast (&context)); - IfFailThrow(hr); + // we originally used GetDataTarget()->GetThreadContext, but + // the implementation uses ShimLocalDataTarget::GetThreadContext which + // depends on OpenThread which might fail with an Access Denied error (see note above) + BOOL success = ::GetThreadContext(hThread, (CONTEXT*)(&context)); + if (!success) + { + LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - Unexpected result from GetThreadContext\n")); + ThrowHR(HRESULT_FROM_GetLastError()); + } + // Read the pointer to the left-side context and the size of the context from the thread context. TADDR lsContextAddr = (TADDR)context.Rcx; DWORD contextSize = (DWORD)context.Rdx; + // Read the expected Rip and Rsp from the thread context. This is used to + // validate the context read from the left-side. TADDR expectedRip = (TADDR)context.R8; TADDR expectedRsp = (TADDR)context.R9; @@ -11198,7 +11240,7 @@ void CordbProcess::HandleSetThreadContextNeeded(DWORD dwThreadId) PCONTEXT pContext = (PCONTEXT)_alloca(contextSize); ULONG32 cbRead; - hr = GetDataTarget()->ReadVirtual(lsContextAddr, reinterpret_cast(pContext), contextSize, &cbRead); + HRESULT hr = GetDataTarget()->ReadVirtual(lsContextAddr, reinterpret_cast(pContext), contextSize, &cbRead); if (FAILED(hr)) { _ASSERTE(!"ReadVirtual failed"); @@ -11232,7 +11274,7 @@ void CordbProcess::HandleSetThreadContextNeeded(DWORD dwThreadId) // The initialize call should fail but return contextSize contextSize = 0; DWORD contextFlags = pContext->ContextFlags; - BOOL success = InitializeContext(NULL, contextFlags, NULL, &contextSize); + success = InitializeContext(NULL, contextFlags, NULL, &contextSize); if(success || GetLastError() != ERROR_INSUFFICIENT_BUFFER) { @@ -11276,6 +11318,7 @@ void CordbProcess::HandleSetThreadContextNeeded(DWORD dwThreadId) DWORD lastError = 0; + // Perform the actual SetThreadContext operation. success = ::SetThreadContext(hThread, pFrameContext); if (!success) { @@ -11285,6 +11328,7 @@ void CordbProcess::HandleSetThreadContextNeeded(DWORD dwThreadId) LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - Set Thread Context Completed: Success=%d GetLastError=%d hr=0x%X\n", success, lastError, HRESULT_FROM_WIN32(lastError))); _ASSERTE(success); + // Now that we have completed the SetThreadContext, resume the thread DWORD suspendCount = ::ResumeThread(hThread); if (suspendCount == (DWORD)-1) { diff --git a/src/coreclr/dlls/mscorrc/mscorrc.rc b/src/coreclr/dlls/mscorrc/mscorrc.rc index 927b287844df7..1d58a0681b584 100644 --- a/src/coreclr/dlls/mscorrc/mscorrc.rc +++ b/src/coreclr/dlls/mscorrc/mscorrc.rc @@ -467,7 +467,6 @@ BEGIN IDS_EE_INVALID_CA "Invalid custom attribute provided." - IDS_EE_THREAD_CANNOT_GET "Unable to retrieve thread information." IDS_EE_THREAD_ABORT_WHILE_SUSPEND "Thread is suspended; attempting to abort." IDS_EE_NOVARIANTRETURN "PInvoke restriction: cannot return variants." diff --git a/src/coreclr/dlls/mscorrc/resource.h b/src/coreclr/dlls/mscorrc/resource.h index 09bf78dfb93c4..964cb7128325d 100644 --- a/src/coreclr/dlls/mscorrc/resource.h +++ b/src/coreclr/dlls/mscorrc/resource.h @@ -232,7 +232,6 @@ #define IDS_EE_INVALID_CA 0x1a10 -#define IDS_EE_THREAD_CANNOT_GET 0x1a15 #define IDS_EE_THREAD_ABORT_WHILE_SUSPEND 0x1a1c #define IDS_EE_NOVARIANTRETURN 0x1a1d diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index 566d1ecb769a4..bf57e9ea28073 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -930,7 +930,6 @@ struct PatchpointInfo; // Cookie types consumed by the code generator (these are opaque values // not inspected by the code generator): -typedef struct CORINFO_ASSEMBLY_STRUCT_* CORINFO_ASSEMBLY_HANDLE; typedef struct CORINFO_MODULE_STRUCT_* CORINFO_MODULE_HANDLE; typedef struct CORINFO_DEPENDENCY_STRUCT_* CORINFO_DEPENDENCY_HANDLE; typedef struct CORINFO_CLASS_STRUCT_* CORINFO_CLASS_HANDLE; @@ -2321,18 +2320,9 @@ class ICorStaticInfo CORINFO_CLASS_HANDLE cls ) = 0; - virtual CORINFO_MODULE_HANDLE getClassModule ( - CORINFO_CLASS_HANDLE cls - ) = 0; - - // Returns the assembly that contains the module "mod". - virtual CORINFO_ASSEMBLY_HANDLE getModuleAssembly ( - CORINFO_MODULE_HANDLE mod - ) = 0; - - // Returns the name of the assembly "assem". - virtual const char* getAssemblyName ( - CORINFO_ASSEMBLY_HANDLE assem + // Returns the assembly name of the class "cls", or nullptr if there is none. + virtual const char* getClassAssemblyName ( + CORINFO_CLASS_HANDLE cls ) = 0; // Allocate and delete process-lifetime objects. Should only be diff --git a/src/coreclr/inc/dacprivate.h b/src/coreclr/inc/dacprivate.h index 305029634406c..62821f71395af 100644 --- a/src/coreclr/inc/dacprivate.h +++ b/src/coreclr/inc/dacprivate.h @@ -425,11 +425,11 @@ enum DacpAppDomainDataStage { STAGE_CLOSED }; -// Information about a BaseDomain (AppDomain, SharedDomain or SystemDomain). +// Information about an AppDomain or SystemDomain. // For types other than AppDomain, some fields (like dwID, DomainLocalBlock, etc.) will be 0/null. struct MSLAYOUT DacpAppDomainData { - // The pointer to the BaseDomain (not necessarily an AppDomain). + // The pointer to the AppDomain or SystemDomain. // It's useful to keep this around in the structure CLRDATA_ADDRESS AppDomainPtr = 0; CLRDATA_ADDRESS AppSecDesc = 0; @@ -455,7 +455,7 @@ struct MSLAYOUT DacpAssemblyData CLRDATA_ADDRESS AssemblyPtr = 0; //useful to have CLRDATA_ADDRESS ClassLoader = 0; CLRDATA_ADDRESS ParentDomain = 0; - CLRDATA_ADDRESS BaseDomainPtr = 0; + CLRDATA_ADDRESS DomainPtr = 0; CLRDATA_ADDRESS AssemblySecDesc = 0; BOOL isDynamic = FALSE; UINT ModuleCount = FALSE; @@ -463,9 +463,9 @@ struct MSLAYOUT DacpAssemblyData BOOL isDomainNeutral = FALSE; // Always false, preserved for backward compatibility DWORD dwLocationFlags = 0; - HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr, CLRDATA_ADDRESS baseDomainPtr) + HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr, CLRDATA_ADDRESS domainPtr) { - return sos->GetAssemblyData(baseDomainPtr, addr, this); + return sos->GetAssemblyData(domainPtr, addr, this); } HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) diff --git a/src/coreclr/inc/eventtracebase.h b/src/coreclr/inc/eventtracebase.h index 316104f649a1d..38868fe528f79 100644 --- a/src/coreclr/inc/eventtracebase.h +++ b/src/coreclr/inc/eventtracebase.h @@ -689,7 +689,6 @@ class Module; class Assembly; class MethodDesc; class MethodTable; -class BaseDomain; class AppDomain; class SString; class CrawlFrame; @@ -750,12 +749,11 @@ namespace ETW #ifdef FEATURE_EVENT_TRACE static VOID SendThreadRundownEvent(); static VOID SendGCRundownEvent(); - static VOID IterateDomain(BaseDomain *pDomain, DWORD enumerationOptions); - static VOID IterateAppDomain(AppDomain * pAppDomain, DWORD enumerationOptions); + static VOID IterateAppDomain(DWORD enumerationOptions); static VOID IterateCollectibleLoaderAllocator(AssemblyLoaderAllocator *pLoaderAllocator, DWORD enumerationOptions); static VOID IterateAssembly(Assembly *pAssembly, DWORD enumerationOptions); static VOID IterateModule(Module *pModule, DWORD enumerationOptions); - static VOID EnumerationHelper(Module *moduleFilter, BaseDomain *domainFilter, DWORD enumerationOptions); + static VOID EnumerationHelper(Module *moduleFilter, DWORD enumerationOptions); static DWORD GetEnumerationOptionsFromRuntimeKeywords(); public: typedef union _EnumerationStructs @@ -839,7 +837,7 @@ namespace ETW static VOID SendModuleEvent(Module *pModule, DWORD dwEventOptions, BOOL bFireDomainModuleEvents=FALSE); static ULONG SendModuleRange(_In_ Module *pModule, _In_ DWORD dwEventOptions); static VOID SendAssemblyEvent(Assembly *pAssembly, DWORD dwEventOptions); - static VOID SendDomainEvent(BaseDomain *pBaseDomain, DWORD dwEventOptions, LPCWSTR wszFriendlyName=NULL); + static VOID SendDomainEvent(DWORD dwEventOptions, LPCWSTR wszFriendlyName=NULL); public: typedef union _LoaderStructs { @@ -877,23 +875,23 @@ namespace ETW }LoaderStructs; - static VOID DomainLoadReal(BaseDomain *pDomain, _In_opt_ LPWSTR wszFriendlyName=NULL); + static VOID DomainLoadReal(_In_opt_ LPWSTR wszFriendlyName=NULL); - static VOID DomainLoad(BaseDomain *pDomain, _In_opt_ LPWSTR wszFriendlyName = NULL) + static VOID DomainLoad(_In_opt_ LPWSTR wszFriendlyName = NULL) { if (ETW_PROVIDER_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER)) { - DomainLoadReal(pDomain, wszFriendlyName); + DomainLoadReal(wszFriendlyName); } } - static VOID DomainUnload(AppDomain *pDomain); + static VOID DomainUnload(); static VOID CollectibleLoaderAllocatorUnload(AssemblyLoaderAllocator *pLoaderAllocator); static VOID ModuleLoad(Module *pModule, LONG liReportedSharedModule); #else public: - static VOID DomainLoad(BaseDomain *pDomain, _In_opt_ LPWSTR wszFriendlyName=NULL) {}; - static VOID DomainUnload(AppDomain *pDomain) {}; + static VOID DomainLoad(_In_opt_ LPWSTR wszFriendlyName=NULL) {}; + static VOID DomainUnload() {}; static VOID CollectibleLoaderAllocatorUnload(AssemblyLoaderAllocator *pLoaderAllocator) {}; static VOID ModuleLoad(Module *pModule, LONG liReportedSharedModule) {}; #endif // FEATURE_EVENT_TRACE @@ -904,7 +902,7 @@ namespace ETW { friend class ETW::EnumerationLog; #ifdef FEATURE_EVENT_TRACE - static VOID SendEventsForJitMethods(BaseDomain *pDomainFilter, LoaderAllocator *pLoaderAllocatorFilter, DWORD dwEventOptions); + static VOID SendEventsForJitMethods(BOOL getCodeVersionIds, LoaderAllocator *pLoaderAllocatorFilter, DWORD dwEventOptions); static VOID SendEventsForJitMethodsHelper( LoaderAllocator *pLoaderAllocatorFilter, DWORD dwEventOptions, diff --git a/src/coreclr/inc/icorjitinfoimpl_generated.h b/src/coreclr/inc/icorjitinfoimpl_generated.h index bbaf43a6ee0ce..ffc4659cb9fb8 100644 --- a/src/coreclr/inc/icorjitinfoimpl_generated.h +++ b/src/coreclr/inc/icorjitinfoimpl_generated.h @@ -193,15 +193,9 @@ bool isValueClass( uint32_t getClassAttribs( CORINFO_CLASS_HANDLE cls) override; -CORINFO_MODULE_HANDLE getClassModule( +const char* getClassAssemblyName( CORINFO_CLASS_HANDLE cls) override; -CORINFO_ASSEMBLY_HANDLE getModuleAssembly( - CORINFO_MODULE_HANDLE mod) override; - -const char* getAssemblyName( - CORINFO_ASSEMBLY_HANDLE assem) override; - void* LongLifetimeMalloc( size_t sz) override; diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index 6aef89b2afd76..bce13e8aabcc3 100644 --- a/src/coreclr/inc/jiteeversionguid.h +++ b/src/coreclr/inc/jiteeversionguid.h @@ -43,11 +43,11 @@ typedef const GUID *LPCGUID; #define GUID_DEFINED #endif // !GUID_DEFINED -constexpr GUID JITEEVersionIdentifier = { /* 7f7fd340-4779-455a-8046-628f3cd8c3c7 */ - 0x7f7fd340, - 0x4779, - 0x455a, - {0x80, 0x46, 0x62, 0x8f, 0x3c, 0xd8, 0xc3, 0xc7} +constexpr GUID JITEEVersionIdentifier = { /* b75a5475-ff22-4078-9551-2024ce03d383 */ + 0xb75a5475, + 0xff22, + 0x4078, + {0x95, 0x51, 0x20, 0x24, 0xce, 0x03, 0xd3, 0x83} }; ////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/coreclr/jit/ICorJitInfo_names_generated.h b/src/coreclr/jit/ICorJitInfo_names_generated.h index 2d3865018d1de..15665a14b69ba 100644 --- a/src/coreclr/jit/ICorJitInfo_names_generated.h +++ b/src/coreclr/jit/ICorJitInfo_names_generated.h @@ -45,9 +45,7 @@ DEF_CLR_API(getTypeInstantiationArgument) DEF_CLR_API(printClassName) DEF_CLR_API(isValueClass) DEF_CLR_API(getClassAttribs) -DEF_CLR_API(getClassModule) -DEF_CLR_API(getModuleAssembly) -DEF_CLR_API(getAssemblyName) +DEF_CLR_API(getClassAssemblyName) DEF_CLR_API(LongLifetimeMalloc) DEF_CLR_API(LongLifetimeFree) DEF_CLR_API(getIsClassInitedFlagAddress) diff --git a/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp b/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp index ff3270192dc5f..f45110fe0caba 100644 --- a/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp +++ b/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp @@ -416,30 +416,12 @@ uint32_t WrapICorJitInfo::getClassAttribs( return temp; } -CORINFO_MODULE_HANDLE WrapICorJitInfo::getClassModule( +const char* WrapICorJitInfo::getClassAssemblyName( CORINFO_CLASS_HANDLE cls) { - API_ENTER(getClassModule); - CORINFO_MODULE_HANDLE temp = wrapHnd->getClassModule(cls); - API_LEAVE(getClassModule); - return temp; -} - -CORINFO_ASSEMBLY_HANDLE WrapICorJitInfo::getModuleAssembly( - CORINFO_MODULE_HANDLE mod) -{ - API_ENTER(getModuleAssembly); - CORINFO_ASSEMBLY_HANDLE temp = wrapHnd->getModuleAssembly(mod); - API_LEAVE(getModuleAssembly); - return temp; -} - -const char* WrapICorJitInfo::getAssemblyName( - CORINFO_ASSEMBLY_HANDLE assem) -{ - API_ENTER(getAssemblyName); - const char* temp = wrapHnd->getAssemblyName(assem); - API_LEAVE(getAssemblyName); + API_ENTER(getClassAssemblyName); + const char* temp = wrapHnd->getClassAssemblyName(cls); + API_LEAVE(getClassAssemblyName); return temp; } diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index 3f28580aba68a..2b9425e6fe502 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -2586,8 +2586,7 @@ void Compiler::compInitOptions(JitFlags* jitFlags) // We have an exclusion list. See if this method is in an assembly that is on the list. // Note that we check this for every method, since we might inline across modules, and // if the inlinee module is on the list, we don't want to use the altjit for it. - const char* methodAssemblyName = info.compCompHnd->getAssemblyName( - info.compCompHnd->getModuleAssembly(info.compCompHnd->getClassModule(info.compClassHnd))); + const char* methodAssemblyName = eeGetClassAssemblyName(info.compClassHnd); if (s_pAltJitExcludeAssembliesList->IsInList(methodAssemblyName)) { opts.altJit = false; @@ -2614,8 +2613,7 @@ void Compiler::compInitOptions(JitFlags* jitFlags) bool assemblyInIncludeList = true; // assume we'll dump, if there's not an include list (or it's empty). if (s_pJitDisasmIncludeAssembliesList != nullptr && !s_pJitDisasmIncludeAssembliesList->IsEmpty()) { - const char* assemblyName = info.compCompHnd->getAssemblyName( - info.compCompHnd->getModuleAssembly(info.compCompHnd->getClassModule(info.compClassHnd))); + const char* assemblyName = eeGetClassAssemblyName(info.compClassHnd); if (!s_pJitDisasmIncludeAssembliesList->IsInList(assemblyName)) { // We have a list, and the current assembly is not in it, so we won't dump. @@ -5238,11 +5236,12 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl m_pLowering->FinalizeOutgoingArgSpace(); // We can not add any new tracked variables after this point. - lvaTrackedFixed = true; + lvaTrackedFixed = true; + const unsigned numBlocksBeforeLSRA = fgBBcount; // Now that lowering is completed we can proceed to perform register allocation // - auto linearScanPhase = [this]() { + auto linearScanPhase = [this] { m_pLinearScan->doLinearScan(); }; DoPhase(this, PHASE_LINEAR_SCAN, linearScanPhase); @@ -5252,8 +5251,25 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl if (opts.OptimizationEnabled()) { - // LSRA and stack level setting can modify the flowgraph. - // Now that it won't change, run post-layout optimizations. + // LSRA may introduce new blocks. If it does, rerun layout. + if ((fgBBcount != numBlocksBeforeLSRA) && JitConfig.JitDoReversePostOrderLayout()) + { + auto lateLayoutPhase = [this] { + fgDoReversePostOrderLayout(); + fgMoveColdBlocks(); + return PhaseStatus::MODIFIED_EVERYTHING; + }; + + DoPhase(this, PHASE_OPTIMIZE_LAYOUT, lateLayoutPhase); + + if (fgFirstColdBlock != nullptr) + { + fgFirstColdBlock = nullptr; + DoPhase(this, PHASE_DETERMINE_FIRST_COLD_BLOCK, &Compiler::fgDetermineFirstColdBlock); + } + } + + // Now that the flowgraph is finalized, run post-layout optimizations. DoPhase(this, PHASE_OPTIMIZE_POST_LAYOUT, &Compiler::optOptimizePostLayout); } @@ -6335,39 +6351,29 @@ int Compiler::compCompile(CORINFO_MODULE_HANDLE classPtr, #ifdef DEBUG if (JitConfig.EnableExtraSuperPmiQueries()) { - // This call to getClassModule/getModuleAssembly/getAssemblyName fails in crossgen2 due to these - // APIs being unimplemented. So disable this extra info for pre-jit mode. See - // https://github.com/dotnet/runtime/issues/48888. - // - // Ditto for some of the class name queries for generic params. - // - if (!compileFlags->IsSet(JitFlags::JIT_FLAG_PREJIT)) - { - // Get the assembly name, to aid finding any particular SuperPMI method context function - (void)info.compCompHnd->getAssemblyName( - info.compCompHnd->getModuleAssembly(info.compCompHnd->getClassModule(info.compClassHnd))); + // Get the assembly name, to aid finding any particular SuperPMI method context function + (void)eeGetClassAssemblyName(info.compClassHnd); - // Fetch class names for the method's generic parameters. - // - CORINFO_SIG_INFO sig; - info.compCompHnd->getMethodSig(info.compMethodHnd, &sig, nullptr); + // Fetch class names for the method's generic parameters. + // + CORINFO_SIG_INFO sig; + info.compCompHnd->getMethodSig(info.compMethodHnd, &sig, nullptr); - const unsigned classInst = sig.sigInst.classInstCount; - if (classInst > 0) + const unsigned classInst = sig.sigInst.classInstCount; + if (classInst > 0) + { + for (unsigned i = 0; i < classInst; i++) { - for (unsigned i = 0; i < classInst; i++) - { - eeGetClassName(sig.sigInst.classInst[i]); - } + eeGetClassName(sig.sigInst.classInst[i]); } + } - const unsigned methodInst = sig.sigInst.methInstCount; - if (methodInst > 0) + const unsigned methodInst = sig.sigInst.methInstCount; + if (methodInst > 0) + { + for (unsigned i = 0; i < methodInst; i++) { - for (unsigned i = 0; i < methodInst; i++) - { - eeGetClassName(sig.sigInst.methInst[i]); - } + eeGetClassName(sig.sigInst.methInst[i]); } } } @@ -9221,8 +9227,7 @@ void JitTimer::PrintCsvMethodStats(Compiler* comp) } else { - const char* methodAssemblyName = comp->info.compCompHnd->getAssemblyName( - comp->info.compCompHnd->getModuleAssembly(comp->info.compCompHnd->getClassModule(comp->info.compClassHnd))); + const char* methodAssemblyName = comp->eeGetClassAssemblyName(comp->info.compClassHnd); fprintf(s_csvFile, "\"%s\",", methodAssemblyName); } fprintf(s_csvFile, "%u,", comp->info.compILCodeSize); diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 6fe0555691bd8..a23a650a805f2 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -5316,6 +5316,8 @@ class Compiler unsigned xcptnIndex, bool putInTryRegion); + BasicBlock* fgNewBBatTryRegionEnd(BBKinds jumpKind, unsigned tryIndex); + void fgInsertBBbefore(BasicBlock* insertBeforeBlk, BasicBlock* newBlk); void fgInsertBBafter(BasicBlock* insertAfterBlk, BasicBlock* newBlk); void fgUnlinkBlock(BasicBlock* block); @@ -8335,6 +8337,8 @@ class Compiler void eePrintObjectDescription(const char* prefix, CORINFO_OBJECT_HANDLE handle); const char* eeGetShortClassName(CORINFO_CLASS_HANDLE clsHnd); + const char* eeGetClassAssemblyName(CORINFO_CLASS_HANDLE clsHnd); + #if defined(DEBUG) unsigned eeTryGetClassSize(CORINFO_CLASS_HANDLE clsHnd); #endif diff --git a/src/coreclr/jit/eeinterface.cpp b/src/coreclr/jit/eeinterface.cpp index fb07912ebf7d9..7ac73a22d27e0 100644 --- a/src/coreclr/jit/eeinterface.cpp +++ b/src/coreclr/jit/eeinterface.cpp @@ -596,6 +596,27 @@ const char* Compiler::eeGetShortClassName(CORINFO_CLASS_HANDLE clsHnd) return printer.GetBuffer(); } +//------------------------------------------------------------------------ +// eeGetClassAssemblyName: +// Get the assembly name of a type. +// If missing information (in SPMI), then return a placeholder string. +// +// Parameters: +// clsHnd - the handle of the class +// +// Return value: +// The name string. +// +const char* Compiler::eeGetClassAssemblyName(CORINFO_CLASS_HANDLE clsHnd) +{ + const char* assemblyName = ""; + eeRunFunctorWithSPMIErrorTrap([&]() { + assemblyName = info.compCompHnd->getClassAssemblyName(clsHnd); + }); + + return assemblyName != nullptr ? assemblyName : ""; +} + void Compiler::eePrintObjectDescription(const char* prefix, CORINFO_OBJECT_HANDLE handle) { const size_t maxStrSize = 64; diff --git a/src/coreclr/jit/emitarm.cpp b/src/coreclr/jit/emitarm.cpp index fd0a27f61818e..902399f58e4fe 100644 --- a/src/coreclr/jit/emitarm.cpp +++ b/src/coreclr/jit/emitarm.cpp @@ -3914,10 +3914,7 @@ void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int va { regNumber rsvdReg = codeGen->rsGetRsvdReg(); emitIns_genStackOffset(rsvdReg, varx, offs, /* isFloatUsage */ true, &baseRegUsed); - - // Ensure the baseReg calculated is correct. - assert(baseRegUsed == reg2); - emitIns_R_R(INS_add, EA_4BYTE, rsvdReg, reg2); + emitIns_R_R(INS_add, EA_4BYTE, rsvdReg, baseRegUsed); emitIns_R_R_I(ins, attr, reg1, rsvdReg, 0); return; } diff --git a/src/coreclr/jit/fgbasic.cpp b/src/coreclr/jit/fgbasic.cpp index f8e7ead56b323..774e456f5e761 100644 --- a/src/coreclr/jit/fgbasic.cpp +++ b/src/coreclr/jit/fgbasic.cpp @@ -6723,6 +6723,39 @@ BasicBlock* Compiler::fgNewBBinRegionWorker(BBKinds jumpKind, return newBlk; } +//----------------------------------------------------------------------------- +// fgNewBBatTryRegionEnd: Creates and inserts a new block at the end of the specified +// try region, updating the try end pointers in the EH table as necessary. +// +// Arguments: +// jumpKind - The jump kind of the new block +// tryIndex - The index of the try region to insert the new block in +// +// Returns: +// The new block +// +BasicBlock* Compiler::fgNewBBatTryRegionEnd(BBKinds jumpKind, unsigned tryIndex) +{ + BasicBlock* const oldTryLast = ehGetDsc(tryIndex)->ebdTryLast; + BasicBlock* const newBlock = fgNewBBafter(jumpKind, oldTryLast, /* extendRegion */ false); + newBlock->setTryIndex(tryIndex); + newBlock->clearHndIndex(); + + // Update this try region's (and all parent try regions') last block pointer + // + for (unsigned XTnum = tryIndex; XTnum < compHndBBtabCount; XTnum++) + { + EHblkDsc* const HBtab = ehGetDsc(XTnum); + if (HBtab->ebdTryLast == oldTryLast) + { + assert((XTnum == tryIndex) || (ehGetDsc(tryIndex)->ebdEnclosingTryIndex != EHblkDsc::NO_ENCLOSING_INDEX)); + fgSetTryEnd(HBtab, newBlock); + } + } + + return newBlock; +} + //------------------------------------------------------------------------ // fgUseThrowHelperBlocks: Determinate does compiler use throw helper blocks. // diff --git a/src/coreclr/jit/lowerarmarch.cpp b/src/coreclr/jit/lowerarmarch.cpp index a74bb3651c88f..6b96564af8668 100644 --- a/src/coreclr/jit/lowerarmarch.cpp +++ b/src/coreclr/jit/lowerarmarch.cpp @@ -4050,47 +4050,49 @@ GenTree* Lowering::LowerHWIntrinsicCndSel(GenTreeHWIntrinsic* cndSelNode) GenTree* nestedOp1 = nestedCndSel->Op(1); GenTree* nestedOp2 = nestedCndSel->Op(2); assert(varTypeIsMask(nestedOp1)); - assert(nestedOp2->OperIsHWIntrinsic()); - NamedIntrinsic nestedOp2Id = nestedOp2->AsHWIntrinsic()->GetHWIntrinsicId(); - - // If the nested op uses Pg/Z, then inactive lanes will result in zeros, so can only transform if - // op3 is all zeros. Such a Csel operation is absorbed into the instruction when emitted. Skip this optimisation - // when the nestedOp is a reduce operation. - - if (nestedOp1->IsMaskAllBitsSet() && !HWIntrinsicInfo::IsReduceOperation(nestedOp2Id) && - (!HWIntrinsicInfo::IsZeroingMaskedOperation(nestedOp2Id) || op3->IsVectorZero())) + if (nestedOp2->OperIsHWIntrinsic()) { - GenTree* nestedOp2 = nestedCndSel->Op(2); - GenTree* nestedOp3 = nestedCndSel->Op(3); + NamedIntrinsic nestedOp2Id = nestedOp2->AsHWIntrinsic()->GetHWIntrinsicId(); - JITDUMP("lowering nested ConditionalSelect HWIntrinisic (before):\n"); - DISPTREERANGE(BlockRange(), cndSelNode); - JITDUMP("\n"); + // If the nested op uses Pg/Z, then inactive lanes will result in zeros, so can only transform if + // op3 is all zeros. Such a Csel operation is absorbed into the instruction when emitted. Skip this + // optimisation when the nestedOp is a reduce operation. - // Transform: - // - // CndSel(mask, CndSel(AllTrue, embeddedMask(trueValOp2), trueValOp3), op3) to - // CndSel(mask, embedded(trueValOp2), op3) - // - cndSelNode->Op(2) = nestedCndSel->Op(2); - if (nestedOp3->IsMaskZero()) - { - BlockRange().Remove(nestedOp3); - } - else + if (nestedOp1->IsMaskAllBitsSet() && !HWIntrinsicInfo::IsReduceOperation(nestedOp2Id) && + (!HWIntrinsicInfo::IsZeroingMaskedOperation(nestedOp2Id) || op3->IsVectorZero())) { - nestedOp3->SetUnusedValue(); - } + GenTree* nestedOp2 = nestedCndSel->Op(2); + GenTree* nestedOp3 = nestedCndSel->Op(3); + + JITDUMP("lowering nested ConditionalSelect HWIntrinisic (before):\n"); + DISPTREERANGE(BlockRange(), cndSelNode); + JITDUMP("\n"); + + // Transform: + // + // CndSel(mask, CndSel(AllTrue, embeddedMask(trueValOp2), trueValOp3), op3) to + // CndSel(mask, embedded(trueValOp2), op3) + // + cndSelNode->Op(2) = nestedCndSel->Op(2); + if (nestedOp3->IsMaskZero()) + { + BlockRange().Remove(nestedOp3); + } + else + { + nestedOp3->SetUnusedValue(); + } - BlockRange().Remove(nestedOp1); - BlockRange().Remove(nestedCndSel); + BlockRange().Remove(nestedOp1); + BlockRange().Remove(nestedCndSel); - JITDUMP("lowering nested ConditionalSelect HWIntrinisic (after):\n"); - DISPTREERANGE(BlockRange(), cndSelNode); - JITDUMP("\n"); + JITDUMP("lowering nested ConditionalSelect HWIntrinisic (after):\n"); + DISPTREERANGE(BlockRange(), cndSelNode); + JITDUMP("\n"); - return cndSelNode; + return cndSelNode; + } } } else if (op1->IsMaskAllBitsSet()) diff --git a/src/coreclr/jit/lsra.cpp b/src/coreclr/jit/lsra.cpp index 763a28989b3a8..3f603fa0c221b 100644 --- a/src/coreclr/jit/lsra.cpp +++ b/src/coreclr/jit/lsra.cpp @@ -9789,10 +9789,26 @@ void LinearScan::resolveEdge(BasicBlock* fromBlock, if (location[targetReg] == REG_NA) { #ifdef TARGET_ARM - regNumber sourceReg = (regNumber)source[targetReg]; - Interval* interval = sourceIntervals[sourceReg]; + // For Arm, check two things: + // 1. If sourceReg relates to DOUBLE interval, then make sure + // the second half of targetReg is not participating in the resolution. + // 2. On the contrary, if targetReg is second half of a DOUBLE interval, + // then make sure the first half is not participating in the resolution. + // Only when both these conditions are met, can we safely assume + // that sourceReg can be moved to targetReg. + regNumber sourceReg = (regNumber)source[targetReg]; + Interval* interval = sourceIntervals[sourceReg]; + Interval* otherTargetInterval = nullptr; + regNumber otherHalfTargetReg = REG_NA; + if (genIsValidFloatReg(targetReg) && !genIsValidDoubleReg(targetReg)) + { + otherHalfTargetReg = REG_PREV(targetReg); + otherTargetInterval = sourceIntervals[otherHalfTargetReg]; + } + if (interval->registerType == TYP_DOUBLE) { + // Condition 1 above. // For ARM32, make sure that both of the float halves of the double register are available. assert(genIsValidDoubleReg(targetReg)); regNumber anotherHalfRegNum = REG_NEXT(targetReg); @@ -9801,11 +9817,22 @@ void LinearScan::resolveEdge(BasicBlock* fromBlock, targetRegsReady.AddRegNumInMask(targetReg); } } + else if ((otherTargetInterval != nullptr) && (otherTargetInterval->registerType == TYP_DOUBLE)) + { + // Condition 2 above. + assert(otherHalfTargetReg != REG_NA); + if (location[otherHalfTargetReg] == REG_NA) + { + targetRegsReady.AddRegNumInMask(targetReg); + } + } else -#endif // TARGET_ARM { targetRegsReady.AddRegNumInMask(targetReg); } +#else + targetRegsReady.AddRegNumInMask(targetReg); +#endif } } @@ -10019,6 +10046,13 @@ void LinearScan::resolveEdge(BasicBlock* fromBlock, { compiler->codeGen->regSet.rsSetRegsModified(genRegMask(tempReg) DEBUGARG(true)); #ifdef TARGET_ARM + Interval* otherTargetInterval = nullptr; + regNumber otherHalfTargetReg = REG_NA; + if (genIsValidFloatReg(targetReg) && !genIsValidDoubleReg(targetReg)) + { + otherHalfTargetReg = REG_PREV(targetReg); + otherTargetInterval = sourceIntervals[otherHalfTargetReg]; + } if (sourceIntervals[fromReg]->registerType == TYP_DOUBLE) { assert(genIsValidDoubleReg(targetReg)); @@ -10027,8 +10061,15 @@ void LinearScan::resolveEdge(BasicBlock* fromBlock, addResolutionForDouble(block, insertionPoint, sourceIntervals, location, tempReg, targetReg, resolveType DEBUG_ARG(fromBlock) DEBUG_ARG(toBlock)); } + else if (otherTargetInterval != nullptr) + { + assert(otherHalfTargetReg != REG_NA); + assert(otherTargetInterval->registerType == TYP_DOUBLE); + + addResolutionForDouble(block, insertionPoint, sourceIntervals, location, tempReg, + otherHalfTargetReg, resolveType DEBUG_ARG(fromBlock) DEBUG_ARG(toBlock)); + } else -#endif // TARGET_ARM { assert(sourceIntervals[targetReg] != nullptr); @@ -10037,6 +10078,14 @@ void LinearScan::resolveEdge(BasicBlock* fromBlock, DEBUG_ARG(resolveTypeName[resolveType])); location[targetReg] = (regNumberSmall)tempReg; } +#else + assert(sourceIntervals[targetReg] != nullptr); + + addResolution(block, insertionPoint, sourceIntervals[targetReg], tempReg, + targetReg DEBUG_ARG(fromBlock) DEBUG_ARG(toBlock) + DEBUG_ARG(resolveTypeName[resolveType])); + location[targetReg] = (regNumberSmall)tempReg; +#endif // TARGET_ARM targetRegsReady |= targetRegMask; } } diff --git a/src/coreclr/jit/optimizer.cpp b/src/coreclr/jit/optimizer.cpp index 27aedb6eb9af2..f9880026eab26 100644 --- a/src/coreclr/jit/optimizer.cpp +++ b/src/coreclr/jit/optimizer.cpp @@ -2891,16 +2891,10 @@ bool Compiler::optCreatePreheader(FlowGraphNaturalLoop* loop) } } - BasicBlock* insertBefore = loop->GetLexicallyTopMostBlock(); - if (!BasicBlock::sameEHRegion(insertBefore, header)) - { - insertBefore = header; - } - - BasicBlock* preheader = fgNewBBbefore(BBJ_ALWAYS, insertBefore, false); + BasicBlock* preheader = fgNewBBbefore(BBJ_ALWAYS, header, false); preheader->SetFlags(BBF_INTERNAL); fgSetEHRegionForNewPreheaderOrExit(preheader); - preheader->bbCodeOffs = insertBefore->bbCodeOffs; + preheader->bbCodeOffs = header->bbCodeOffs; JITDUMP("Created new preheader " FMT_BB " for " FMT_LP "\n", preheader->bbNum, loop->GetIndex()); @@ -3003,21 +2997,11 @@ bool Compiler::optCanonicalizeExit(FlowGraphNaturalLoop* loop, BasicBlock* exit) { // Branches to a BBJ_CALLFINALLY _must_ come from inside its associated // try region, and when we have callfinally thunks the BBJ_CALLFINALLY - // is outside it. First try to see if the lexically bottom most block - // is part of the try; if so, inserting after that is a good choice. + // is outside it. Thus, insert newExit at the end of the finally's + // try region. BasicBlock* finallyBlock = exit->GetTarget(); assert(finallyBlock->hasHndIndex()); - BasicBlock* bottom = loop->GetLexicallyBottomMostBlock(); - if (bottom->hasTryIndex() && (bottom->getTryIndex() == finallyBlock->getHndIndex()) && !bottom->hasHndIndex()) - { - newExit = fgNewBBafter(BBJ_ALWAYS, bottom, true); - } - else - { - // Otherwise just do the heavy-handed thing and insert it anywhere in the right region. - newExit = fgNewBBinRegion(BBJ_ALWAYS, finallyBlock->bbHndIndex, 0, nullptr, /* putInFilter */ false, - /* runRarely */ false, /* insertAtEnd */ true); - } + newExit = fgNewBBatTryRegionEnd(BBJ_ALWAYS, finallyBlock->getHndIndex()); } else { diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeAugments.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeAugments.cs index 7db11a8204177..4b0967e372bbc 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeAugments.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeAugments.cs @@ -120,6 +120,32 @@ public static unsafe Array NewMultiDimArray(RuntimeTypeHandle typeHandleForArray return Array.NewMultiDimArray(typeHandleForArrayType.ToMethodTable(), pImmutableLengths, lengths.Length); } + public static unsafe void SetArrayValue(Array array, int[] indices, object value) + { + MethodTable* elementMT = array.ElementMethodTable; + + if (elementMT->IsPointer || elementMT->IsFunctionPointer) + { + Debug.Assert(value.GetMethodTable()->ValueTypeSize == IntPtr.Size); + elementMT = value.GetMethodTable(); + } + + if (elementMT->IsValueType) + { + Debug.Assert(value.GetMethodTable()->IsValueType && elementMT->ValueTypeSize == value.GetMethodTable()->ValueTypeSize); + nint flattenedIndex = array.GetFlattenedIndex(indices); + ref byte element = ref Unsafe.AddByteOffset(ref MemoryMarshal.GetArrayDataReference(array), (nuint)flattenedIndex * array.ElementSize); + RuntimeImports.RhUnbox(value, ref element, elementMT); + } + else + { + RuntimeImports.RhCheckArrayStore(array, value); + nint flattenedIndex = array.GetFlattenedIndex(indices); + ref object element = ref Unsafe.Add(ref Unsafe.As(ref MemoryMarshal.GetArrayDataReference(array)), flattenedIndex); + element = value; + } + } + public static IntPtr GetAllocateObjectHelperForType(RuntimeTypeHandle type) { return RuntimeImports.RhGetRuntimeHelperForType(type.ToMethodTable(), RuntimeHelperKind.AllocateObject); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Array.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Array.NativeAot.cs index 58378b92a9c5f..faa4d51e93532 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Array.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Array.NativeAot.cs @@ -727,7 +727,7 @@ private unsafe nint GetFlattenedIndex(int rawIndex) return rawIndex; } - private unsafe nint GetFlattenedIndex(ReadOnlySpan indices) + internal unsafe nint GetFlattenedIndex(ReadOnlySpan indices) { // Checked by the caller Debug.Assert(indices.Length == Rank); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeArrayTypeInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeArrayTypeInfo.cs index ab9fd61a3587e..1f2f374b2436e 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeArrayTypeInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeArrayTypeInfo.cs @@ -213,7 +213,7 @@ internal sealed override IEnumerable SyntheticMethods for (int i = 0; i < rank; i++) indices[i] = (int)(args[i]); object value = args[rank]; - array.SetValue(value, indices); + RuntimeAugments.SetArrayValue(array, indices, value); return null; } ); diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index 987bbc6508f13..d766ded60142e 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -2092,12 +2092,17 @@ private uint getClassAttribsInternal(TypeDesc type) return (uint)result; } - private CORINFO_MODULE_STRUCT_* getClassModule(CORINFO_CLASS_STRUCT_* cls) - { throw new NotImplementedException("getClassModule"); } - private CORINFO_ASSEMBLY_STRUCT_* getModuleAssembly(CORINFO_MODULE_STRUCT_* mod) - { throw new NotImplementedException("getModuleAssembly"); } - private byte* getAssemblyName(CORINFO_ASSEMBLY_STRUCT_* assem) - { throw new NotImplementedException("getAssemblyName"); } + private byte* getClassAssemblyName(CORINFO_CLASS_STRUCT_* cls) + { + TypeDesc type = HandleToObject(cls); + + if (type is MetadataType mdType) + { + return (byte*)GetPin(StringToUTF8(mdType.Module.Assembly.GetName().Name)); + } + + return null; + } #pragma warning disable CA1822 // Mark members as static private void* LongLifetimeMalloc(UIntPtr sz) diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs index 9213d42aba327..26291e015b428 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs @@ -614,42 +614,12 @@ private static uint _getClassAttribs(IntPtr thisHandle, IntPtr* ppException, COR } [UnmanagedCallersOnly] - private static CORINFO_MODULE_STRUCT_* _getClassModule(IntPtr thisHandle, IntPtr* ppException, CORINFO_CLASS_STRUCT_* cls) + private static byte* _getClassAssemblyName(IntPtr thisHandle, IntPtr* ppException, CORINFO_CLASS_STRUCT_* cls) { var _this = GetThis(thisHandle); try { - return _this.getClassModule(cls); - } - catch (Exception ex) - { - *ppException = _this.AllocException(ex); - return default; - } - } - - [UnmanagedCallersOnly] - private static CORINFO_ASSEMBLY_STRUCT_* _getModuleAssembly(IntPtr thisHandle, IntPtr* ppException, CORINFO_MODULE_STRUCT_* mod) - { - var _this = GetThis(thisHandle); - try - { - return _this.getModuleAssembly(mod); - } - catch (Exception ex) - { - *ppException = _this.AllocException(ex); - return default; - } - } - - [UnmanagedCallersOnly] - private static byte* _getAssemblyName(IntPtr thisHandle, IntPtr* ppException, CORINFO_ASSEMBLY_STRUCT_* assem) - { - var _this = GetThis(thisHandle); - try - { - return _this.getAssemblyName(assem); + return _this.getClassAssemblyName(cls); } catch (Exception ex) { @@ -2623,7 +2593,7 @@ private static uint _getJitFlags(IntPtr thisHandle, IntPtr* ppException, CORJIT_ private static IntPtr GetUnmanagedCallbacks() { - void** callbacks = (void**)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 177); + void** callbacks = (void**)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 175); callbacks[0] = (delegate* unmanaged)&_isIntrinsic; callbacks[1] = (delegate* unmanaged)&_notifyMethodInfoUsage; @@ -2666,142 +2636,140 @@ private static IntPtr GetUnmanagedCallbacks() callbacks[38] = (delegate* unmanaged)&_printClassName; callbacks[39] = (delegate* unmanaged)&_isValueClass; callbacks[40] = (delegate* unmanaged)&_getClassAttribs; - callbacks[41] = (delegate* unmanaged)&_getClassModule; - callbacks[42] = (delegate* unmanaged)&_getModuleAssembly; - callbacks[43] = (delegate* unmanaged)&_getAssemblyName; - callbacks[44] = (delegate* unmanaged)&_LongLifetimeMalloc; - callbacks[45] = (delegate* unmanaged)&_LongLifetimeFree; - callbacks[46] = (delegate* unmanaged)&_getIsClassInitedFlagAddress; - callbacks[47] = (delegate* unmanaged)&_getClassThreadStaticDynamicInfo; - callbacks[48] = (delegate* unmanaged)&_getClassStaticDynamicInfo; - callbacks[49] = (delegate* unmanaged)&_getStaticBaseAddress; - callbacks[50] = (delegate* unmanaged)&_getClassSize; - callbacks[51] = (delegate* unmanaged)&_getHeapClassSize; - callbacks[52] = (delegate* unmanaged)&_canAllocateOnStack; - callbacks[53] = (delegate* unmanaged)&_getClassAlignmentRequirement; - callbacks[54] = (delegate* unmanaged)&_getClassGClayout; - callbacks[55] = (delegate* unmanaged)&_getClassNumInstanceFields; - callbacks[56] = (delegate* unmanaged)&_getFieldInClass; - callbacks[57] = (delegate* unmanaged)&_getTypeLayout; - callbacks[58] = (delegate* unmanaged)&_checkMethodModifier; - callbacks[59] = (delegate* unmanaged)&_getNewHelper; - callbacks[60] = (delegate* unmanaged)&_getNewArrHelper; - callbacks[61] = (delegate* unmanaged)&_getCastingHelper; - callbacks[62] = (delegate* unmanaged)&_getSharedCCtorHelper; - callbacks[63] = (delegate* unmanaged)&_getTypeForBox; - callbacks[64] = (delegate* unmanaged)&_getTypeForBoxOnStack; - callbacks[65] = (delegate* unmanaged)&_getBoxHelper; - callbacks[66] = (delegate* unmanaged)&_getUnBoxHelper; - callbacks[67] = (delegate* unmanaged)&_getRuntimeTypePointer; - callbacks[68] = (delegate* unmanaged)&_isObjectImmutable; - callbacks[69] = (delegate* unmanaged)&_getStringChar; - callbacks[70] = (delegate* unmanaged)&_getObjectType; - callbacks[71] = (delegate* unmanaged)&_getReadyToRunHelper; - callbacks[72] = (delegate* unmanaged)&_getReadyToRunDelegateCtorHelper; - callbacks[73] = (delegate* unmanaged)&_initClass; - callbacks[74] = (delegate* unmanaged)&_classMustBeLoadedBeforeCodeIsRun; - callbacks[75] = (delegate* unmanaged)&_getBuiltinClass; - callbacks[76] = (delegate* unmanaged)&_getTypeForPrimitiveValueClass; - callbacks[77] = (delegate* unmanaged)&_getTypeForPrimitiveNumericClass; - callbacks[78] = (delegate* unmanaged)&_canCast; - callbacks[79] = (delegate* unmanaged)&_compareTypesForCast; - callbacks[80] = (delegate* unmanaged)&_compareTypesForEquality; - callbacks[81] = (delegate* unmanaged)&_isMoreSpecificType; - callbacks[82] = (delegate* unmanaged)&_isExactType; - callbacks[83] = (delegate* unmanaged)&_isGenericType; - callbacks[84] = (delegate* unmanaged)&_isNullableType; - callbacks[85] = (delegate* unmanaged)&_isEnum; - callbacks[86] = (delegate* unmanaged)&_getParentType; - callbacks[87] = (delegate* unmanaged)&_getChildType; - callbacks[88] = (delegate* unmanaged)&_isSDArray; - callbacks[89] = (delegate* unmanaged)&_getArrayRank; - callbacks[90] = (delegate* unmanaged)&_getArrayIntrinsicID; - callbacks[91] = (delegate* unmanaged)&_getArrayInitializationData; - callbacks[92] = (delegate* unmanaged)&_canAccessClass; - callbacks[93] = (delegate* unmanaged)&_printFieldName; - callbacks[94] = (delegate* unmanaged)&_getFieldClass; - callbacks[95] = (delegate* unmanaged)&_getFieldType; - callbacks[96] = (delegate* unmanaged)&_getFieldOffset; - callbacks[97] = (delegate* unmanaged)&_getFieldInfo; - callbacks[98] = (delegate* unmanaged)&_getThreadLocalFieldInfo; - callbacks[99] = (delegate* unmanaged)&_getThreadLocalStaticBlocksInfo; - callbacks[100] = (delegate* unmanaged)&_getThreadLocalStaticInfo_NativeAOT; - callbacks[101] = (delegate* unmanaged)&_isFieldStatic; - callbacks[102] = (delegate* unmanaged)&_getArrayOrStringLength; - callbacks[103] = (delegate* unmanaged)&_getBoundaries; - callbacks[104] = (delegate* unmanaged)&_setBoundaries; - callbacks[105] = (delegate* unmanaged)&_getVars; - callbacks[106] = (delegate* unmanaged)&_setVars; - callbacks[107] = (delegate* unmanaged)&_reportRichMappings; - callbacks[108] = (delegate* unmanaged)&_reportMetadata; - callbacks[109] = (delegate* unmanaged)&_allocateArray; - callbacks[110] = (delegate* unmanaged)&_freeArray; - callbacks[111] = (delegate* unmanaged)&_getArgNext; - callbacks[112] = (delegate* unmanaged)&_getArgType; - callbacks[113] = (delegate* unmanaged)&_getExactClasses; - callbacks[114] = (delegate* unmanaged)&_getArgClass; - callbacks[115] = (delegate* unmanaged)&_getHFAType; - callbacks[116] = (delegate* unmanaged)&_runWithErrorTrap; - callbacks[117] = (delegate* unmanaged)&_runWithSPMIErrorTrap; - callbacks[118] = (delegate* unmanaged)&_getEEInfo; - callbacks[119] = (delegate* unmanaged)&_getJitTimeLogFilename; - callbacks[120] = (delegate* unmanaged)&_getMethodDefFromMethod; - callbacks[121] = (delegate* unmanaged)&_printMethodName; - callbacks[122] = (delegate* unmanaged)&_getMethodNameFromMetadata; - callbacks[123] = (delegate* unmanaged)&_getMethodHash; - callbacks[124] = (delegate* unmanaged)&_getSystemVAmd64PassStructInRegisterDescriptor; - callbacks[125] = (delegate* unmanaged)&_getSwiftLowering; - callbacks[126] = (delegate* unmanaged)&_getFpStructLowering; - callbacks[127] = (delegate* unmanaged)&_getThreadTLSIndex; - callbacks[128] = (delegate* unmanaged)&_getAddrOfCaptureThreadGlobal; - callbacks[129] = (delegate* unmanaged)&_getHelperFtn; - callbacks[130] = (delegate* unmanaged)&_getFunctionEntryPoint; - callbacks[131] = (delegate* unmanaged)&_getFunctionFixedEntryPoint; - callbacks[132] = (delegate* unmanaged)&_getMethodSync; - callbacks[133] = (delegate* unmanaged)&_getLazyStringLiteralHelper; - callbacks[134] = (delegate* unmanaged)&_embedModuleHandle; - callbacks[135] = (delegate* unmanaged)&_embedClassHandle; - callbacks[136] = (delegate* unmanaged)&_embedMethodHandle; - callbacks[137] = (delegate* unmanaged)&_embedFieldHandle; - callbacks[138] = (delegate* unmanaged)&_embedGenericHandle; - callbacks[139] = (delegate* unmanaged)&_getLocationOfThisType; - callbacks[140] = (delegate* unmanaged)&_getAddressOfPInvokeTarget; - callbacks[141] = (delegate* unmanaged)&_GetCookieForPInvokeCalliSig; - callbacks[142] = (delegate* unmanaged)&_canGetCookieForPInvokeCalliSig; - callbacks[143] = (delegate* unmanaged)&_getJustMyCodeHandle; - callbacks[144] = (delegate* unmanaged)&_GetProfilingHandle; - callbacks[145] = (delegate* unmanaged)&_getCallInfo; - callbacks[146] = (delegate* unmanaged)&_getStaticFieldContent; - callbacks[147] = (delegate* unmanaged)&_getObjectContent; - callbacks[148] = (delegate* unmanaged)&_getStaticFieldCurrentClass; - callbacks[149] = (delegate* unmanaged)&_getVarArgsHandle; - callbacks[150] = (delegate* unmanaged)&_canGetVarArgsHandle; - callbacks[151] = (delegate* unmanaged)&_constructStringLiteral; - callbacks[152] = (delegate* unmanaged)&_emptyStringLiteral; - callbacks[153] = (delegate* unmanaged)&_getFieldThreadLocalStoreID; - callbacks[154] = (delegate* unmanaged)&_GetDelegateCtor; - callbacks[155] = (delegate* unmanaged)&_MethodCompileComplete; - callbacks[156] = (delegate* unmanaged)&_getTailCallHelpers; - callbacks[157] = (delegate* unmanaged)&_convertPInvokeCalliToCall; - callbacks[158] = (delegate* unmanaged)&_notifyInstructionSetUsage; - callbacks[159] = (delegate* unmanaged)&_updateEntryPointForTailCall; - callbacks[160] = (delegate* unmanaged)&_allocMem; - callbacks[161] = (delegate* unmanaged)&_reserveUnwindInfo; - callbacks[162] = (delegate* unmanaged)&_allocUnwindInfo; - callbacks[163] = (delegate* unmanaged)&_allocGCInfo; - callbacks[164] = (delegate* unmanaged)&_setEHcount; - callbacks[165] = (delegate* unmanaged)&_setEHinfo; - callbacks[166] = (delegate* unmanaged)&_logMsg; - callbacks[167] = (delegate* unmanaged)&_doAssert; - callbacks[168] = (delegate* unmanaged)&_reportFatalError; - callbacks[169] = (delegate* unmanaged)&_getPgoInstrumentationResults; - callbacks[170] = (delegate* unmanaged)&_allocPgoInstrumentationBySchema; - callbacks[171] = (delegate* unmanaged)&_recordCallSite; - callbacks[172] = (delegate* unmanaged)&_recordRelocation; - callbacks[173] = (delegate* unmanaged)&_getRelocTypeHint; - callbacks[174] = (delegate* unmanaged)&_getExpectedTargetArchitecture; - callbacks[175] = (delegate* unmanaged)&_getJitFlags; - callbacks[176] = (delegate* unmanaged)&_getSpecialCopyHelper; + callbacks[41] = (delegate* unmanaged)&_getClassAssemblyName; + callbacks[42] = (delegate* unmanaged)&_LongLifetimeMalloc; + callbacks[43] = (delegate* unmanaged)&_LongLifetimeFree; + callbacks[44] = (delegate* unmanaged)&_getIsClassInitedFlagAddress; + callbacks[45] = (delegate* unmanaged)&_getClassThreadStaticDynamicInfo; + callbacks[46] = (delegate* unmanaged)&_getClassStaticDynamicInfo; + callbacks[47] = (delegate* unmanaged)&_getStaticBaseAddress; + callbacks[48] = (delegate* unmanaged)&_getClassSize; + callbacks[49] = (delegate* unmanaged)&_getHeapClassSize; + callbacks[50] = (delegate* unmanaged)&_canAllocateOnStack; + callbacks[51] = (delegate* unmanaged)&_getClassAlignmentRequirement; + callbacks[52] = (delegate* unmanaged)&_getClassGClayout; + callbacks[53] = (delegate* unmanaged)&_getClassNumInstanceFields; + callbacks[54] = (delegate* unmanaged)&_getFieldInClass; + callbacks[55] = (delegate* unmanaged)&_getTypeLayout; + callbacks[56] = (delegate* unmanaged)&_checkMethodModifier; + callbacks[57] = (delegate* unmanaged)&_getNewHelper; + callbacks[58] = (delegate* unmanaged)&_getNewArrHelper; + callbacks[59] = (delegate* unmanaged)&_getCastingHelper; + callbacks[60] = (delegate* unmanaged)&_getSharedCCtorHelper; + callbacks[61] = (delegate* unmanaged)&_getTypeForBox; + callbacks[62] = (delegate* unmanaged)&_getTypeForBoxOnStack; + callbacks[63] = (delegate* unmanaged)&_getBoxHelper; + callbacks[64] = (delegate* unmanaged)&_getUnBoxHelper; + callbacks[65] = (delegate* unmanaged)&_getRuntimeTypePointer; + callbacks[66] = (delegate* unmanaged)&_isObjectImmutable; + callbacks[67] = (delegate* unmanaged)&_getStringChar; + callbacks[68] = (delegate* unmanaged)&_getObjectType; + callbacks[69] = (delegate* unmanaged)&_getReadyToRunHelper; + callbacks[70] = (delegate* unmanaged)&_getReadyToRunDelegateCtorHelper; + callbacks[71] = (delegate* unmanaged)&_initClass; + callbacks[72] = (delegate* unmanaged)&_classMustBeLoadedBeforeCodeIsRun; + callbacks[73] = (delegate* unmanaged)&_getBuiltinClass; + callbacks[74] = (delegate* unmanaged)&_getTypeForPrimitiveValueClass; + callbacks[75] = (delegate* unmanaged)&_getTypeForPrimitiveNumericClass; + callbacks[76] = (delegate* unmanaged)&_canCast; + callbacks[77] = (delegate* unmanaged)&_compareTypesForCast; + callbacks[78] = (delegate* unmanaged)&_compareTypesForEquality; + callbacks[79] = (delegate* unmanaged)&_isMoreSpecificType; + callbacks[80] = (delegate* unmanaged)&_isExactType; + callbacks[81] = (delegate* unmanaged)&_isGenericType; + callbacks[82] = (delegate* unmanaged)&_isNullableType; + callbacks[83] = (delegate* unmanaged)&_isEnum; + callbacks[84] = (delegate* unmanaged)&_getParentType; + callbacks[85] = (delegate* unmanaged)&_getChildType; + callbacks[86] = (delegate* unmanaged)&_isSDArray; + callbacks[87] = (delegate* unmanaged)&_getArrayRank; + callbacks[88] = (delegate* unmanaged)&_getArrayIntrinsicID; + callbacks[89] = (delegate* unmanaged)&_getArrayInitializationData; + callbacks[90] = (delegate* unmanaged)&_canAccessClass; + callbacks[91] = (delegate* unmanaged)&_printFieldName; + callbacks[92] = (delegate* unmanaged)&_getFieldClass; + callbacks[93] = (delegate* unmanaged)&_getFieldType; + callbacks[94] = (delegate* unmanaged)&_getFieldOffset; + callbacks[95] = (delegate* unmanaged)&_getFieldInfo; + callbacks[96] = (delegate* unmanaged)&_getThreadLocalFieldInfo; + callbacks[97] = (delegate* unmanaged)&_getThreadLocalStaticBlocksInfo; + callbacks[98] = (delegate* unmanaged)&_getThreadLocalStaticInfo_NativeAOT; + callbacks[99] = (delegate* unmanaged)&_isFieldStatic; + callbacks[100] = (delegate* unmanaged)&_getArrayOrStringLength; + callbacks[101] = (delegate* unmanaged)&_getBoundaries; + callbacks[102] = (delegate* unmanaged)&_setBoundaries; + callbacks[103] = (delegate* unmanaged)&_getVars; + callbacks[104] = (delegate* unmanaged)&_setVars; + callbacks[105] = (delegate* unmanaged)&_reportRichMappings; + callbacks[106] = (delegate* unmanaged)&_reportMetadata; + callbacks[107] = (delegate* unmanaged)&_allocateArray; + callbacks[108] = (delegate* unmanaged)&_freeArray; + callbacks[109] = (delegate* unmanaged)&_getArgNext; + callbacks[110] = (delegate* unmanaged)&_getArgType; + callbacks[111] = (delegate* unmanaged)&_getExactClasses; + callbacks[112] = (delegate* unmanaged)&_getArgClass; + callbacks[113] = (delegate* unmanaged)&_getHFAType; + callbacks[114] = (delegate* unmanaged)&_runWithErrorTrap; + callbacks[115] = (delegate* unmanaged)&_runWithSPMIErrorTrap; + callbacks[116] = (delegate* unmanaged)&_getEEInfo; + callbacks[117] = (delegate* unmanaged)&_getJitTimeLogFilename; + callbacks[118] = (delegate* unmanaged)&_getMethodDefFromMethod; + callbacks[119] = (delegate* unmanaged)&_printMethodName; + callbacks[120] = (delegate* unmanaged)&_getMethodNameFromMetadata; + callbacks[121] = (delegate* unmanaged)&_getMethodHash; + callbacks[122] = (delegate* unmanaged)&_getSystemVAmd64PassStructInRegisterDescriptor; + callbacks[123] = (delegate* unmanaged)&_getSwiftLowering; + callbacks[124] = (delegate* unmanaged)&_getFpStructLowering; + callbacks[125] = (delegate* unmanaged)&_getThreadTLSIndex; + callbacks[126] = (delegate* unmanaged)&_getAddrOfCaptureThreadGlobal; + callbacks[127] = (delegate* unmanaged)&_getHelperFtn; + callbacks[128] = (delegate* unmanaged)&_getFunctionEntryPoint; + callbacks[129] = (delegate* unmanaged)&_getFunctionFixedEntryPoint; + callbacks[130] = (delegate* unmanaged)&_getMethodSync; + callbacks[131] = (delegate* unmanaged)&_getLazyStringLiteralHelper; + callbacks[132] = (delegate* unmanaged)&_embedModuleHandle; + callbacks[133] = (delegate* unmanaged)&_embedClassHandle; + callbacks[134] = (delegate* unmanaged)&_embedMethodHandle; + callbacks[135] = (delegate* unmanaged)&_embedFieldHandle; + callbacks[136] = (delegate* unmanaged)&_embedGenericHandle; + callbacks[137] = (delegate* unmanaged)&_getLocationOfThisType; + callbacks[138] = (delegate* unmanaged)&_getAddressOfPInvokeTarget; + callbacks[139] = (delegate* unmanaged)&_GetCookieForPInvokeCalliSig; + callbacks[140] = (delegate* unmanaged)&_canGetCookieForPInvokeCalliSig; + callbacks[141] = (delegate* unmanaged)&_getJustMyCodeHandle; + callbacks[142] = (delegate* unmanaged)&_GetProfilingHandle; + callbacks[143] = (delegate* unmanaged)&_getCallInfo; + callbacks[144] = (delegate* unmanaged)&_getStaticFieldContent; + callbacks[145] = (delegate* unmanaged)&_getObjectContent; + callbacks[146] = (delegate* unmanaged)&_getStaticFieldCurrentClass; + callbacks[147] = (delegate* unmanaged)&_getVarArgsHandle; + callbacks[148] = (delegate* unmanaged)&_canGetVarArgsHandle; + callbacks[149] = (delegate* unmanaged)&_constructStringLiteral; + callbacks[150] = (delegate* unmanaged)&_emptyStringLiteral; + callbacks[151] = (delegate* unmanaged)&_getFieldThreadLocalStoreID; + callbacks[152] = (delegate* unmanaged)&_GetDelegateCtor; + callbacks[153] = (delegate* unmanaged)&_MethodCompileComplete; + callbacks[154] = (delegate* unmanaged)&_getTailCallHelpers; + callbacks[155] = (delegate* unmanaged)&_convertPInvokeCalliToCall; + callbacks[156] = (delegate* unmanaged)&_notifyInstructionSetUsage; + callbacks[157] = (delegate* unmanaged)&_updateEntryPointForTailCall; + callbacks[158] = (delegate* unmanaged)&_allocMem; + callbacks[159] = (delegate* unmanaged)&_reserveUnwindInfo; + callbacks[160] = (delegate* unmanaged)&_allocUnwindInfo; + callbacks[161] = (delegate* unmanaged)&_allocGCInfo; + callbacks[162] = (delegate* unmanaged)&_setEHcount; + callbacks[163] = (delegate* unmanaged)&_setEHinfo; + callbacks[164] = (delegate* unmanaged)&_logMsg; + callbacks[165] = (delegate* unmanaged)&_doAssert; + callbacks[166] = (delegate* unmanaged)&_reportFatalError; + callbacks[167] = (delegate* unmanaged)&_getPgoInstrumentationResults; + callbacks[168] = (delegate* unmanaged)&_allocPgoInstrumentationBySchema; + callbacks[169] = (delegate* unmanaged)&_recordCallSite; + callbacks[170] = (delegate* unmanaged)&_recordRelocation; + callbacks[171] = (delegate* unmanaged)&_getRelocTypeHint; + callbacks[172] = (delegate* unmanaged)&_getExpectedTargetArchitecture; + callbacks[173] = (delegate* unmanaged)&_getJitFlags; + callbacks[174] = (delegate* unmanaged)&_getSpecialCopyHelper; return (IntPtr)callbacks; } diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs b/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs index 4be84d0c316f8..74b260578fd00 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs @@ -52,10 +52,6 @@ public struct CORINFO_MODULE_STRUCT_ { } - public struct CORINFO_ASSEMBLY_STRUCT_ - { - } - public struct CORINFO_CONTEXT_STRUCT { } diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt index 76d3ea9d3864a..bf98cf70a7e2d 100644 --- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt +++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt @@ -144,7 +144,6 @@ CORINFO_METHOD_HANDLE,CORINFO_METHOD_STRUCT_* CORINFO_FIELD_HANDLE,CORINFO_FIELD_STRUCT_* CORINFO_OBJECT_HANDLE,CORINFO_OBJECT_STRUCT_* CORINFO_CLASS_HANDLE,CORINFO_CLASS_STRUCT_* -CORINFO_ASSEMBLY_HANDLE,CORINFO_ASSEMBLY_STRUCT_* CORINFO_JUST_MY_CODE_HANDLE,CORINFO_JUST_MY_CODE_HANDLE_* CORINFO_MODULE_HANDLE*,CORINFO_MODULE_STRUCT_** CORINFO_CLASS_HANDLE*,CORINFO_CLASS_STRUCT_** @@ -205,9 +204,7 @@ FUNCTIONS size_t printClassName(CORINFO_CLASS_HANDLE cls, char* buffer, size_t bufferSize, size_t* pRequiredBufferSize) bool isValueClass(CORINFO_CLASS_HANDLE cls) uint32_t getClassAttribs(CORINFO_CLASS_HANDLE cls) - CORINFO_MODULE_HANDLE getClassModule(CORINFO_CLASS_HANDLE cls) - CORINFO_ASSEMBLY_HANDLE getModuleAssembly(CORINFO_MODULE_HANDLE mod) - const char* getAssemblyName(CORINFO_ASSEMBLY_HANDLE assem) + const char* getClassAssemblyName(CORINFO_CLASS_HANDLE cls) void* LongLifetimeMalloc(size_t sz) void LongLifetimeFree(void* obj) bool getIsClassInitedFlagAddress(CORINFO_CLASS_HANDLE cls, CORINFO_CONST_LOOKUP* addr, int* offset) diff --git a/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h b/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h index 0ba43d2a45885..0e9bde0b4def1 100644 --- a/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h +++ b/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h @@ -52,9 +52,7 @@ struct JitInterfaceCallbacks size_t (* printClassName)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls, char* buffer, size_t bufferSize, size_t* pRequiredBufferSize); bool (* isValueClass)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); uint32_t (* getClassAttribs)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); - CORINFO_MODULE_HANDLE (* getClassModule)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); - CORINFO_ASSEMBLY_HANDLE (* getModuleAssembly)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_MODULE_HANDLE mod); - const char* (* getAssemblyName)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_ASSEMBLY_HANDLE assem); + const char* (* getClassAssemblyName)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); void* (* LongLifetimeMalloc)(void * thisHandle, CorInfoExceptionClass** ppException, size_t sz); void (* LongLifetimeFree)(void * thisHandle, CorInfoExceptionClass** ppException, void* obj); bool (* getIsClassInitedFlagAddress)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls, CORINFO_CONST_LOOKUP* addr, int* offset); @@ -607,29 +605,11 @@ class JitInterfaceWrapper : public ICorJitInfo return temp; } - virtual CORINFO_MODULE_HANDLE getClassModule( + virtual const char* getClassAssemblyName( CORINFO_CLASS_HANDLE cls) { CorInfoExceptionClass* pException = nullptr; - CORINFO_MODULE_HANDLE temp = _callbacks->getClassModule(_thisHandle, &pException, cls); - if (pException != nullptr) throw pException; - return temp; -} - - virtual CORINFO_ASSEMBLY_HANDLE getModuleAssembly( - CORINFO_MODULE_HANDLE mod) -{ - CorInfoExceptionClass* pException = nullptr; - CORINFO_ASSEMBLY_HANDLE temp = _callbacks->getModuleAssembly(_thisHandle, &pException, mod); - if (pException != nullptr) throw pException; - return temp; -} - - virtual const char* getAssemblyName( - CORINFO_ASSEMBLY_HANDLE assem) -{ - CorInfoExceptionClass* pException = nullptr; - const char* temp = _callbacks->getAssemblyName(_thisHandle, &pException, assem); + const char* temp = _callbacks->getClassAssemblyName(_thisHandle, &pException, cls); if (pException != nullptr) throw pException; return temp; } diff --git a/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h b/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h index e00f86d1b6458..64b394309f567 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h @@ -102,9 +102,7 @@ LWM(GetLocationOfThisType, DWORDLONG, Agnostic_CORINFO_LOOKUP_KIND) LWM(IsIntrinsic, DWORDLONG, DWORD) LWM(NotifyMethodInfoUsage, DWORDLONG, DWORD) LWM(GetMethodAttribs, DWORDLONG, DWORD) -LWM(GetClassModule, DWORDLONG, DWORDLONG) -LWM(GetModuleAssembly, DWORDLONG, DWORDLONG) -LWM(GetAssemblyName, DWORDLONG, DWORD) +LWM(GetClassAssemblyName, DWORDLONG, DWORD) LWM(GetMethodClass, DWORDLONG, DWORDLONG) LWM(GetMethodDefFromMethod, DWORDLONG, DWORD) LWM(GetMethodHash, DWORDLONG, DWORD) diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp index ddfc401aff1f2..36974d6534a71 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp @@ -816,93 +816,44 @@ DWORD MethodContext::repGetMethodAttribs(CORINFO_METHOD_HANDLE methodHandle) return value; } -void MethodContext::recGetClassModule(CORINFO_CLASS_HANDLE cls, CORINFO_MODULE_HANDLE mod) +void MethodContext::recGetClassAssemblyName(CORINFO_CLASS_HANDLE cls, const char* assemblyName) { - if (GetClassModule == nullptr) - GetClassModule = new LightWeightMap(); - - DWORDLONG key = CastHandle(cls); - DWORDLONG value = CastHandle(mod); - GetClassModule->Add(key, value); - DEBUG_REC(dmpGetClassModule(key, value)); -} -void MethodContext::dmpGetClassModule(DWORDLONG key, DWORDLONG value) -{ - printf("GetClassModule cls-%016" PRIX64 ", mod-%016" PRIX64 "", key, value); -} -CORINFO_MODULE_HANDLE MethodContext::repGetClassModule(CORINFO_CLASS_HANDLE cls) -{ - DWORDLONG key = CastHandle(cls); - DWORDLONG value = LookupByKeyOrMiss(GetClassModule, key, ": key %016" PRIX64 "", key); - DEBUG_REP(dmpGetClassModule(key, value)); - CORINFO_MODULE_HANDLE result = (CORINFO_MODULE_HANDLE)value; - return result; -} - -void MethodContext::recGetModuleAssembly(CORINFO_MODULE_HANDLE mod, CORINFO_ASSEMBLY_HANDLE assem) -{ - if (GetModuleAssembly == nullptr) - GetModuleAssembly = new LightWeightMap(); - - DWORDLONG key = CastHandle(mod); - DWORDLONG value = CastHandle(assem); - GetModuleAssembly->Add(key, value); - DEBUG_REC(dmpGetModuleAssembly(key, value)); -} -void MethodContext::dmpGetModuleAssembly(DWORDLONG key, DWORDLONG value) -{ - printf("GetModuleAssembly mod-%016" PRIX64 ", assem-%016" PRIX64 "", key, value); -} -CORINFO_ASSEMBLY_HANDLE MethodContext::repGetModuleAssembly(CORINFO_MODULE_HANDLE mod) -{ - DWORDLONG key = CastHandle(mod); - DWORDLONG value = LookupByKeyOrMiss(GetModuleAssembly, key, ": key %016" PRIX64 "", key); - DEBUG_REP(dmpGetModuleAssembly(key, value)); - CORINFO_ASSEMBLY_HANDLE result = (CORINFO_ASSEMBLY_HANDLE)value; - return result; -} - -void MethodContext::recGetAssemblyName(CORINFO_ASSEMBLY_HANDLE assem, const char* assemblyName) -{ - if (GetAssemblyName == nullptr) - GetAssemblyName = new LightWeightMap(); + if (GetClassAssemblyName == nullptr) + GetClassAssemblyName = new LightWeightMap(); DWORD value; if (assemblyName != nullptr) { - value = GetAssemblyName->AddBuffer((const unsigned char*)assemblyName, (DWORD)strlen(assemblyName) + 1); + value = GetClassAssemblyName->AddBuffer((const unsigned char*)assemblyName, (DWORD)strlen(assemblyName) + 1); } else { value = (DWORD)-1; } - DWORDLONG key = CastHandle(assem); - GetAssemblyName->Add(key, value); - DEBUG_REC(dmpGetAssemblyName(key, value)); + DWORDLONG key = CastHandle(cls); + GetClassAssemblyName->Add(key, value); + DEBUG_REC(dmpGetClassAssemblyName(key, value)); } -void MethodContext::dmpGetAssemblyName(DWORDLONG key, DWORD value) +void MethodContext::dmpGetClassAssemblyName(DWORDLONG key, DWORD value) { - const char* assemblyName = (const char*)GetAssemblyName->GetBuffer(value); - printf("GetAssemblyName assem-%016" PRIX64 ", value-%u '%s'", key, value, assemblyName); - GetAssemblyName->Unlock(); + const char* assemblyName = (const char*)GetClassAssemblyName->GetBuffer(value); + printf("GetClassAssemblyName cls-%016" PRIX64 ", value-%u '%s'", key, value, assemblyName); + GetClassAssemblyName->Unlock(); } -const char* MethodContext::repGetAssemblyName(CORINFO_ASSEMBLY_HANDLE assem) +const char* MethodContext::repGetClassAssemblyName(CORINFO_CLASS_HANDLE cls) { - DWORDLONG key = CastHandle(assem); - const char* result = "hackishAssemblyName"; - DWORD value = (DWORD)-1; - int itemIndex = -1; - if (GetAssemblyName != nullptr) - { - itemIndex = GetAssemblyName->GetIndex(key); - } - if (itemIndex >= 0) + DWORDLONG key = CastHandle(cls); + DWORD value = LookupByKeyOrMiss(GetClassAssemblyName, key, ": key %016" PRIX64 "", key); + const char* result = nullptr; + + DEBUG_REP(dmpGetClassAssemblyName(key, value)); + + if (value != (DWORD)-1) { - value = GetAssemblyName->Get(key); - result = (const char*)GetAssemblyName->GetBuffer(value); + result = (const char*)GetClassAssemblyName->GetBuffer(value); } - DEBUG_REP(dmpGetAssemblyName(key, value)); + return result; } diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h index ffe0e7aaa5bdc..0fd63deb1bad4 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h @@ -130,17 +130,9 @@ class MethodContext void dmpGetMethodAttribs(DWORDLONG key, DWORD value); DWORD repGetMethodAttribs(CORINFO_METHOD_HANDLE methodHandle); - void recGetClassModule(CORINFO_CLASS_HANDLE cls, CORINFO_MODULE_HANDLE mod); - void dmpGetClassModule(DWORDLONG key, DWORDLONG value); - CORINFO_MODULE_HANDLE repGetClassModule(CORINFO_CLASS_HANDLE cls); - - void recGetModuleAssembly(CORINFO_MODULE_HANDLE mod, CORINFO_ASSEMBLY_HANDLE assem); - void dmpGetModuleAssembly(DWORDLONG key, DWORDLONG value); - CORINFO_ASSEMBLY_HANDLE repGetModuleAssembly(CORINFO_MODULE_HANDLE mod); - - void recGetAssemblyName(CORINFO_ASSEMBLY_HANDLE assem, const char* assemblyName); - void dmpGetAssemblyName(DWORDLONG key, DWORD value); - const char* repGetAssemblyName(CORINFO_ASSEMBLY_HANDLE assem); + void recGetClassAssemblyName(CORINFO_CLASS_HANDLE cls, const char* assemblyName); + void dmpGetClassAssemblyName(DWORDLONG key, DWORD value); + const char* repGetClassAssemblyName(CORINFO_CLASS_HANDLE cls); void recGetVars(CORINFO_METHOD_HANDLE ftn, ULONG32* cVars, ICorDebugInfo::ILVarInfo** vars, bool* extendOthers); void dmpGetVars(DWORDLONG key, const Agnostic_GetVars& value); @@ -1158,9 +1150,9 @@ enum mcPackets Packet_AllocPgoInstrumentationBySchema = 186, Packet_GetPgoInstrumentationResults = 187, Packet_GetDefaultComparerClass = 188, - Packet_GetClassModule = 189, - Packet_GetModuleAssembly = 190, - Packet_GetAssemblyName = 191, + //Packet_GetClassModule = 189, + //Packet_GetModuleAssembly = 190, + //Packet_GetAssemblyName = 191, Packet_IsIntrinsic = 192, Packet_UpdateEntryPointForTailCall = 193, //Packet_GetLoongArch64PassStructInRegisterFlags = 194, @@ -1194,6 +1186,7 @@ enum mcPackets Packet_GetTypeDefinition = 222, Packet_GetFpStructLowering = 223, Packet_GetSpecialCopyHelper = 224, + Packet_GetClassAssemblyName = 225, }; void SetDebugDumpVariables(); diff --git a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp index 5cf11bf9420df..274ebcaa7eb00 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp @@ -491,29 +491,12 @@ uint32_t interceptor_ICJI::getClassAttribs(CORINFO_CLASS_HANDLE cls) return temp; } -CORINFO_MODULE_HANDLE interceptor_ICJI::getClassModule(CORINFO_CLASS_HANDLE cls) +// Returns the assembly name of the class "cls". +const char* interceptor_ICJI::getClassAssemblyName(CORINFO_CLASS_HANDLE cls) { - mc->cr->AddCall("getClassModule"); - CORINFO_MODULE_HANDLE temp = original_ICorJitInfo->getClassModule(cls); - mc->recGetClassModule(cls, temp); - return temp; -} - -// Returns the assembly that contains the module "mod". -CORINFO_ASSEMBLY_HANDLE interceptor_ICJI::getModuleAssembly(CORINFO_MODULE_HANDLE mod) -{ - mc->cr->AddCall("getModuleAssembly"); - CORINFO_ASSEMBLY_HANDLE temp = original_ICorJitInfo->getModuleAssembly(mod); - mc->recGetModuleAssembly(mod, temp); - return temp; -} - -// Returns the name of the assembly "assem". -const char* interceptor_ICJI::getAssemblyName(CORINFO_ASSEMBLY_HANDLE assem) -{ - mc->cr->AddCall("getAssemblyName"); - const char* temp = original_ICorJitInfo->getAssemblyName(assem); - mc->recGetAssemblyName(assem, temp); + mc->cr->AddCall("getClassAssemblyName"); + const char* temp = original_ICorJitInfo->getClassAssemblyName(cls); + mc->recGetClassAssemblyName(cls, temp); return temp; } diff --git a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp index 9d5eb18dfc4d9..bba12312ee908 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp @@ -348,25 +348,11 @@ uint32_t interceptor_ICJI::getClassAttribs( return original_ICorJitInfo->getClassAttribs(cls); } -CORINFO_MODULE_HANDLE interceptor_ICJI::getClassModule( +const char* interceptor_ICJI::getClassAssemblyName( CORINFO_CLASS_HANDLE cls) { - mcs->AddCall("getClassModule"); - return original_ICorJitInfo->getClassModule(cls); -} - -CORINFO_ASSEMBLY_HANDLE interceptor_ICJI::getModuleAssembly( - CORINFO_MODULE_HANDLE mod) -{ - mcs->AddCall("getModuleAssembly"); - return original_ICorJitInfo->getModuleAssembly(mod); -} - -const char* interceptor_ICJI::getAssemblyName( - CORINFO_ASSEMBLY_HANDLE assem) -{ - mcs->AddCall("getAssemblyName"); - return original_ICorJitInfo->getAssemblyName(assem); + mcs->AddCall("getClassAssemblyName"); + return original_ICorJitInfo->getClassAssemblyName(cls); } void* interceptor_ICJI::LongLifetimeMalloc( diff --git a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp index 8e3bff4eb7067..2c789226b7f56 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp @@ -307,22 +307,10 @@ uint32_t interceptor_ICJI::getClassAttribs( return original_ICorJitInfo->getClassAttribs(cls); } -CORINFO_MODULE_HANDLE interceptor_ICJI::getClassModule( +const char* interceptor_ICJI::getClassAssemblyName( CORINFO_CLASS_HANDLE cls) { - return original_ICorJitInfo->getClassModule(cls); -} - -CORINFO_ASSEMBLY_HANDLE interceptor_ICJI::getModuleAssembly( - CORINFO_MODULE_HANDLE mod) -{ - return original_ICorJitInfo->getModuleAssembly(mod); -} - -const char* interceptor_ICJI::getAssemblyName( - CORINFO_ASSEMBLY_HANDLE assem) -{ - return original_ICorJitInfo->getAssemblyName(assem); + return original_ICorJitInfo->getClassAssemblyName(cls); } void* interceptor_ICJI::LongLifetimeMalloc( diff --git a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp index c3c4fd276490e..0fc1df067dd7d 100644 --- a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp @@ -416,24 +416,11 @@ uint32_t MyICJI::getClassAttribs(CORINFO_CLASS_HANDLE cls) return jitInstance->mc->repGetClassAttribs(cls); } -CORINFO_MODULE_HANDLE MyICJI::getClassModule(CORINFO_CLASS_HANDLE cls) +// Returns the assembly name of the class "cls". +const char* MyICJI::getClassAssemblyName(CORINFO_CLASS_HANDLE cls) { - jitInstance->mc->cr->AddCall("getClassModule"); - return jitInstance->mc->repGetClassModule(cls); -} - -// Returns the assembly that contains the module "mod". -CORINFO_ASSEMBLY_HANDLE MyICJI::getModuleAssembly(CORINFO_MODULE_HANDLE mod) -{ - jitInstance->mc->cr->AddCall("getModuleAssembly"); - return jitInstance->mc->repGetModuleAssembly(mod); -} - -// Returns the name of the assembly "assem". -const char* MyICJI::getAssemblyName(CORINFO_ASSEMBLY_HANDLE assem) -{ - jitInstance->mc->cr->AddCall("getAssemblyName"); - return jitInstance->mc->repGetAssemblyName(assem); + jitInstance->mc->cr->AddCall("getClassAssemblyName"); + return jitInstance->mc->repGetClassAssemblyName(cls); } // Allocate and delete process-lifetime objects. Should only be diff --git a/src/coreclr/vm/appdomain.cpp b/src/coreclr/vm/appdomain.cpp index 8d3395cd8ebbd..287823cac17f6 100644 --- a/src/coreclr/vm/appdomain.cpp +++ b/src/coreclr/vm/appdomain.cpp @@ -1546,15 +1546,15 @@ void SystemDomain::NotifyProfilerStartup() { BEGIN_PROFILER_CALLBACK(CORProfilerTrackAppDomainLoads()); - _ASSERTE(System()->DefaultDomain()); - (&g_profControlBlock)->AppDomainCreationStarted((AppDomainID) System()->DefaultDomain()); + _ASSERTE(AppDomain::GetCurrentDomain()); + (&g_profControlBlock)->AppDomainCreationStarted((AppDomainID) AppDomain::GetCurrentDomain()); END_PROFILER_CALLBACK(); } { BEGIN_PROFILER_CALLBACK(CORProfilerTrackAppDomainLoads()); - _ASSERTE(System()->DefaultDomain()); - (&g_profControlBlock)->AppDomainCreationFinished((AppDomainID) System()->DefaultDomain(), S_OK); + _ASSERTE(AppDomain::GetCurrentDomain()); + (&g_profControlBlock)->AppDomainCreationFinished((AppDomainID) AppDomain::GetCurrentDomain(), S_OK); END_PROFILER_CALLBACK(); } } @@ -1585,15 +1585,15 @@ HRESULT SystemDomain::NotifyProfilerShutdown() { BEGIN_PROFILER_CALLBACK(CORProfilerTrackAppDomainLoads()); - _ASSERTE(System()->DefaultDomain()); - (&g_profControlBlock)->AppDomainShutdownStarted((AppDomainID) System()->DefaultDomain()); + _ASSERTE(AppDomain::GetCurrentDomain()); + (&g_profControlBlock)->AppDomainShutdownStarted((AppDomainID) AppDomain::GetCurrentDomain()); END_PROFILER_CALLBACK(); } { BEGIN_PROFILER_CALLBACK(CORProfilerTrackAppDomainLoads()); - _ASSERTE(System()->DefaultDomain()); - (&g_profControlBlock)->AppDomainShutdownFinished((AppDomainID) System()->DefaultDomain(), S_OK); + _ASSERTE(AppDomain::GetCurrentDomain()); + (&g_profControlBlock)->AppDomainShutdownFinished((AppDomainID) AppDomain::GetCurrentDomain(), S_OK); END_PROFILER_CALLBACK(); } return (S_OK); @@ -2481,6 +2481,9 @@ DomainAssembly *AppDomain::LoadDomainAssemblyInternal(AssemblySpec* pIdentity, fileLock = FileLoadLock::Create(lock, pPEAssembly, pDomainAssembly); pDomainAssembly.SuppressRelease(); pamTracker->SuppressRelease(); + + // Set the assembly module to be tenured now that we know it won't be deleted + pDomainAssembly->GetAssembly()->SetIsTenured(); if (pDomainAssembly->IsCollectible()) { // We add the assembly to the LoaderAllocator only when we are sure that it can be added @@ -2516,7 +2519,9 @@ DomainAssembly *AppDomain::LoadDomainAssemblyInternal(AssemblySpec* pIdentity, } } else + { result->EnsureLoadLevel(targetLevel); + } // Cache result in all cases, since found pPEAssembly could be from a different AssemblyRef than pIdentity if (pIdentity == NULL) diff --git a/src/coreclr/vm/appdomain.hpp b/src/coreclr/vm/appdomain.hpp index b357f6e1a512a..ef026a3704de7 100644 --- a/src/coreclr/vm/appdomain.hpp +++ b/src/coreclr/vm/appdomain.hpp @@ -2014,7 +2014,7 @@ class SystemDomain : public BaseDomain m_pDelayedUnloadListOfLoaderAllocators=NULL; - m_GlobalAllocator.Init(this); + m_GlobalAllocator.Init(); } #endif @@ -2023,7 +2023,6 @@ class SystemDomain : public BaseDomain GlobalLoaderAllocator m_GlobalAllocator; - InlineSString<100> m_BaseLibrary; InlineSString<100> m_SystemDirectory; diff --git a/src/coreclr/vm/assembly.cpp b/src/coreclr/vm/assembly.cpp index 9c4209c268bcf..0d344df01297b 100644 --- a/src/coreclr/vm/assembly.cpp +++ b/src/coreclr/vm/assembly.cpp @@ -456,7 +456,7 @@ Assembly *Assembly::CreateDynamic(AssemblyBinder* pBinder, NativeAssemblyNamePar // Some of the initialization functions are not virtual. Call through the derived class // to prevent calling the base class version. - pCollectibleLoaderAllocator->Init(pDomain); + pCollectibleLoaderAllocator->Init(); // Setup the managed proxy now, but do not actually transfer ownership to it. // Once everything is setup and nothing can fail anymore, the ownership will be @@ -531,6 +531,7 @@ Assembly *Assembly::CreateDynamic(AssemblyBinder* pBinder, NativeAssemblyNamePar pLoaderAllocator.SuppressRelease(); } + // Set the assembly module to be tenured now that we know it won't be deleted pAssem->SetIsTenured(); pRetVal = pAssem; } diff --git a/src/coreclr/vm/assemblynative.cpp b/src/coreclr/vm/assemblynative.cpp index 94220a1e35bad..cad3829428c15 100644 --- a/src/coreclr/vm/assemblynative.cpp +++ b/src/coreclr/vm/assemblynative.cpp @@ -513,16 +513,16 @@ extern "C" void QCALLTYPE AssemblyNative_GetForwardedType(QCall::AssemblyHandle END_QCALL; } -FCIMPL1(FC_BOOL_RET, AssemblyNative::IsDynamic, AssemblyBaseObject* pAssemblyUNSAFE) +FCIMPL1(FC_BOOL_RET, AssemblyNative::GetIsDynamic, Assembly* pAssembly) { - FCALL_CONTRACT; - - ASSEMBLYREF refAssembly = (ASSEMBLYREF)ObjectToOBJECTREF(pAssemblyUNSAFE); - - if (refAssembly == NULL) - FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle")); + CONTRACTL + { + FCALL_CHECK; + PRECONDITION(CheckPointer(pAssembly)); + } + CONTRACTL_END; - FC_RETURN_BOOL(refAssembly->GetAssembly()->GetPEAssembly()->IsReflectionEmit()); + FC_RETURN_BOOL(pAssembly->GetPEAssembly()->IsReflectionEmit()); } FCIMPLEND @@ -1205,7 +1205,7 @@ extern "C" INT_PTR QCALLTYPE AssemblyNative_InitializeAssemblyLoadContext(INT_PT GCX_PREEMP(); // Some of the initialization functions are not virtual. Call through the derived class // to prevent calling the base class version. - loaderAllocator->Init(pCurDomain); + loaderAllocator->Init(); loaderAllocator->InitVirtualCallStubManager(); // Setup the managed proxy now, but do not actually transfer ownership to it. diff --git a/src/coreclr/vm/assemblynative.hpp b/src/coreclr/vm/assemblynative.hpp index 80ae3da8c2bd5..1ff73a406c70a 100644 --- a/src/coreclr/vm/assemblynative.hpp +++ b/src/coreclr/vm/assemblynative.hpp @@ -19,10 +19,6 @@ class CustomAssemblyBinder; class AssemblyNative { - friend class Assembly; - friend class BaseDomain; - friend class DomainAssembly; - public: static Assembly* LoadFromPEImage(AssemblyBinder* pBinder, PEImage *pImage, bool excludeAppPaths = false); @@ -35,7 +31,7 @@ class AssemblyNative // static - FCDECL1(FC_BOOL_RET, IsDynamic, AssemblyBaseObject * pAssemblyUNSAFE); + FCDECL1(FC_BOOL_RET, GetIsDynamic, Assembly* pAssembly); }; extern "C" uint32_t QCALLTYPE AssemblyNative_GetAssemblyCount(); diff --git a/src/coreclr/vm/clsload.cpp b/src/coreclr/vm/clsload.cpp index 0c42ca20161ee..ce23d1e907f31 100644 --- a/src/coreclr/vm/clsload.cpp +++ b/src/coreclr/vm/clsload.cpp @@ -836,27 +836,6 @@ void ClassLoader::EnsureLoaded(TypeHandle typeHnd, ClassLoadLevel level) #endif // DACCESS_COMPILE } -/*static*/ -void ClassLoader::TryEnsureLoaded(TypeHandle typeHnd, ClassLoadLevel level) -{ - WRAPPER_NO_CONTRACT; - -#ifndef DACCESS_COMPILE // Nothing to do for the DAC case - - EX_TRY - { - ClassLoader::EnsureLoaded(typeHnd, level); - } - EX_CATCH - { - // Some type may not load successfully. For eg. generic instantiations - // that do not satisfy the constraints of the type arguments. - } - EX_END_CATCH(RethrowTerminalExceptions); - -#endif // DACCESS_COMPILE -} - /* static */ TypeHandle ClassLoader::LookupTypeKey(const TypeKey *pKey, EETypeHashTable *pTable) { diff --git a/src/coreclr/vm/clsload.hpp b/src/coreclr/vm/clsload.hpp index 95afa2716ec9f..f6cb4f06c0021 100644 --- a/src/coreclr/vm/clsload.hpp +++ b/src/coreclr/vm/clsload.hpp @@ -564,11 +564,6 @@ class ClassLoader Module * pLookInThisModuleOnly, Loader::LoadFlag loadFlag); - static PTR_Module ComputeLoaderModuleForCompilation(Module *pDefinitionModule, // the module that declares the generic type or method - mdToken token, - Instantiation classInst, // the type arguments to the type (if any) - Instantiation methodInst); // the type arguments to the method (if any) - public: void Init(AllocMemTracker *pamTracker); @@ -718,7 +713,6 @@ class ClassLoader BOOL * pfUsesTypeForwarder = NULL); static void EnsureLoaded(TypeHandle typeHnd, ClassLoadLevel level = CLASS_LOADED); - static void TryEnsureLoaded(TypeHandle typeHnd, ClassLoadLevel level = CLASS_LOADED); public: // Look up a class by name @@ -889,24 +883,7 @@ class ClassLoader static void DECLSPEC_NORETURN ThrowTypeLoadException(const TypeKey *pKey, UINT resIDWhy); - - BOOL IsNested(const NameHandle* pName, mdToken *mdEncloser); - static BOOL IsNested(ModuleBase *pModude, mdToken typeDefOrRef, mdToken *mdEncloser); - public: - // Helpers for FindClassModule() - BOOL CompareNestedEntryWithTypeDef(IMDInternalImport *pImport, - mdTypeDef mdCurrent, - EEClassHashTable *pClassHash, - PTR_EEClassHashEntry pEntry); - BOOL CompareNestedEntryWithTypeRef(IMDInternalImport *pImport, - mdTypeRef mdCurrent, - EEClassHashTable *pClassHash, - PTR_EEClassHashEntry pEntry); - BOOL CompareNestedEntryWithExportedType(IMDInternalImport *pImport, - mdExportedType mdCurrent, - EEClassHashTable *pClassHash, - PTR_EEClassHashEntry pEntry); //Attempts to find/load/create a type handle but does not throw // if used in "find" mode. diff --git a/src/coreclr/vm/codeman.cpp b/src/coreclr/vm/codeman.cpp index d019affc33b33..0314a2920f074 100644 --- a/src/coreclr/vm/codeman.cpp +++ b/src/coreclr/vm/codeman.cpp @@ -2376,6 +2376,16 @@ HeapList* LoaderCodeHeap::CreateCodeHeap(CodeHeapRequestInfo *pInfo, LoaderHeap } else { + // Include internal CodeHeap structures in the reserve + allocationSize = ALIGN_UP(allocationSize, VIRTUAL_ALLOC_RESERVE_GRANULARITY); + reserveSize = max(reserveSize, allocationSize); + + if (reserveSize != (DWORD) reserveSize) + { + _ASSERTE(!"reserveSize does not fit in a DWORD"); + EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE); + } + if (loAddr != NULL || hiAddr != NULL) { #ifdef _DEBUG diff --git a/src/coreclr/vm/comsynchronizable.cpp b/src/coreclr/vm/comsynchronizable.cpp index 73cc949ec66d5..7f1751aaa15f5 100644 --- a/src/coreclr/vm/comsynchronizable.cpp +++ b/src/coreclr/vm/comsynchronizable.cpp @@ -362,63 +362,17 @@ extern "C" void QCALLTYPE ThreadNative_SetPriority(QCall::ObjectHandleOnStack th END_QCALL; } -FCIMPL1(FC_BOOL_RET, ThreadNative::IsAlive, ThreadBaseObject* pThisUNSAFE) +extern "C" void QCALLTYPE ThreadNative_GetCurrentThread(QCall::ObjectHandleOnStack thread) { - FCALL_CONTRACT; - - if (pThisUNSAFE==NULL) - FCThrowRes(kNullReferenceException, W("NullReference_This")); - - THREADBASEREF thisRef(pThisUNSAFE); - BOOL ret = false; - - // Keep managed Thread object alive, since the native object's - // lifetime is tied to the managed object's finalizer. And with - // resurrection, it may be possible to get a dangling pointer here - - // consider both protecting thisRef and setting the managed object's - // Thread* to NULL in the GC's ScanForFinalization method. - HELPER_METHOD_FRAME_BEGIN_RET_1(thisRef); - - Thread *thread = thisRef->GetInternal(); - - if (thread == 0) - COMPlusThrow(kThreadStateException, IDS_EE_THREAD_CANNOT_GET); - - ret = ThreadIsRunning(thread); - - HELPER_METHOD_POLL(); - HELPER_METHOD_FRAME_END(); - - FC_RETURN_BOOL(ret); -} -FCIMPLEND - -NOINLINE static Object* GetCurrentThreadHelper() -{ - FCALL_CONTRACT; - FC_INNER_PROLOG(ThreadNative::GetCurrentThread); - OBJECTREF refRetVal = NULL; - - HELPER_METHOD_FRAME_BEGIN_RET_ATTRIB_1(Frame::FRAME_ATTR_EXACT_DEPTH|Frame::FRAME_ATTR_CAPTURE_DEPTH_2, refRetVal); - refRetVal = GetThread()->GetExposedObject(); - HELPER_METHOD_FRAME_END(); + QCALL_CONTRACT; - FC_INNER_EPILOG(); - return OBJECTREFToObject(refRetVal); -} + BEGIN_QCALL; -FCIMPL0(Object*, ThreadNative::GetCurrentThread) -{ - FCALL_CONTRACT; - OBJECTHANDLE ExposedObject = GetThread()->m_ExposedObject; - _ASSERTE(ExposedObject != 0); //Thread's constructor always initializes its GCHandle - Object* result = *((Object**) ExposedObject); - if (result != 0) - return result; + GCX_COOP(); + thread.Set(GetThread()->GetExposedObject()); - FC_INNER_RETURN(Object*, GetCurrentThreadHelper()); + END_QCALL; } -FCIMPLEND extern "C" UINT64 QCALLTYPE ThreadNative_GetCurrentOSThreadId() { @@ -442,33 +396,36 @@ extern "C" UINT64 QCALLTYPE ThreadNative_GetCurrentOSThreadId() return threadId; } -FCIMPL1(void, ThreadNative::Initialize, ThreadBaseObject* pThisUNSAFE) +extern "C" void QCALLTYPE ThreadNative_Initialize(QCall::ObjectHandleOnStack t) { - FCALL_CONTRACT; + QCALL_CONTRACT; - THREADBASEREF pThis = (THREADBASEREF) pThisUNSAFE; + BEGIN_QCALL; - HELPER_METHOD_FRAME_BEGIN_1(pThis); + GCX_COOP(); + + THREADBASEREF threadRef = NULL; + GCPROTECT_BEGIN(threadRef) + threadRef = (THREADBASEREF)t.Get(); - _ASSERTE(pThis != NULL); - _ASSERTE(pThis->m_InternalThread == NULL); + _ASSERTE(threadRef != NULL); + _ASSERTE(threadRef->GetInternal() == NULL); // if we don't have an internal Thread object associated with this exposed object, // now is our first opportunity to create one. - Thread *unstarted = SetupUnstartedThread(); - + Thread* unstarted = SetupUnstartedThread(); PREFIX_ASSUME(unstarted != NULL); - pThis->SetInternal(unstarted); - pThis->SetManagedThreadId(unstarted->GetThreadId()); - unstarted->SetExposedObject(pThis); + threadRef->SetInternal(unstarted); + threadRef->SetManagedThreadId(unstarted->GetThreadId()); + unstarted->SetExposedObject(threadRef); // Initialize the thread priority to normal. - pThis->SetPriority(ThreadNative::PRIORITY_NORMAL); + threadRef->SetPriority(ThreadNative::PRIORITY_NORMAL); - HELPER_METHOD_FRAME_END(); + GCPROTECT_END(); + END_QCALL; } -FCIMPLEND // Return whether or not this is a background thread. FCIMPL1(FC_BOOL_RET, ThreadNative::GetIsBackground, ThreadBaseObject* pThisUNSAFE) @@ -489,57 +446,43 @@ FCIMPL1(FC_BOOL_RET, ThreadNative::GetIsBackground, ThreadBaseObject* pThisUNSAF FCIMPLEND // Deliver the state of the thread as a consistent set of bits. -// This copied in VM\EEDbgInterfaceImpl.h's -// CorDebugUserState GetUserState( Thread *pThread ) -// , so propagate changes to both functions -FCIMPL1(INT32, ThreadNative::GetThreadState, ThreadBaseObject* pThisUNSAFE) +// Duplicate logic in DacDbiInterfaceImpl::GetPartialUserState() +extern "C" INT32 QCALLTYPE ThreadNative_GetThreadState(QCall::ThreadHandle thread) { - FCALL_CONTRACT; - - INT32 res = 0; - Thread::ThreadState state; - - if (pThisUNSAFE==NULL) - FCThrowRes(kNullReferenceException, W("NullReference_This")); - - // validate the thread. Failure here implies that the thread was finalized - // and then resurrected. - Thread *thread = pThisUNSAFE->GetInternal(); - - if (!thread) - FCThrowEx(kThreadStateException, IDS_EE_THREAD_CANNOT_GET, NULL, NULL, NULL); + CONTRACTL + { + QCALL_CHECK_NO_GC_TRANSITION; + PRECONDITION(thread != NULL); + } + CONTRACTL_END; - HELPER_METHOD_FRAME_BEGIN_RET_0(); + INT32 res = 0; // grab a snapshot - state = thread->GetSnapshotState(); + Thread::ThreadState state = thread->GetSnapshotState(); if (state & Thread::TS_Background) - res |= ThreadBackground; + res |= ThreadNative::ThreadBackground; if (state & Thread::TS_Unstarted) - res |= ThreadUnstarted; + res |= ThreadNative::ThreadUnstarted; // Don't report a StopRequested if the thread has actually stopped. if (state & Thread::TS_Dead) { - res |= ThreadStopped; + res |= ThreadNative::ThreadStopped; } else { if (state & Thread::TS_AbortRequested) - res |= ThreadAbortRequested; + res |= ThreadNative::ThreadAbortRequested; } if (state & Thread::TS_Interruptible) - res |= ThreadWaitSleepJoin; - - HELPER_METHOD_POLL(); - HELPER_METHOD_FRAME_END(); + res |= ThreadNative::ThreadWaitSleepJoin; return res; } -FCIMPLEND #ifdef FEATURE_COMINTEROP_APARTMENT_SUPPORT @@ -942,16 +885,12 @@ extern "C" void QCALLTYPE ThreadNative_DisableComObjectEagerCleanup(QCall::Threa { CONTRACTL { - QCALL_CHECK; + QCALL_CHECK_NO_GC_TRANSITION; PRECONDITION(thread != NULL); } CONTRACTL_END; - BEGIN_QCALL; - thread->SetDisableComObjectEagerCleanup(); - - END_QCALL; } #endif //FEATURE_COMINTEROP diff --git a/src/coreclr/vm/comsynchronizable.h b/src/coreclr/vm/comsynchronizable.h index 9180216deeea9..b7c64c529084f 100644 --- a/src/coreclr/vm/comsynchronizable.h +++ b/src/coreclr/vm/comsynchronizable.h @@ -52,13 +52,9 @@ friend class ThreadBaseObject; ThreadAbortRequested = 128, }; - static FCDECL1(FC_BOOL_RET, IsAlive, ThreadBaseObject* pThisUNSAFE); - static FCDECL1(void, Initialize, ThreadBaseObject* pThisUNSAFE); static FCDECL1(FC_BOOL_RET, GetIsBackground, ThreadBaseObject* pThisUNSAFE); - static FCDECL1(INT32, GetThreadState, ThreadBaseObject* pThisUNSAFE); static FCDECL0(INT32, GetOptimalMaxSpinWaitsPerSpinIteration); - static FCDECL0(Object*, GetCurrentThread); static FCDECL1(void, Finalize, ThreadBaseObject* pThis); static FCDECL1(FC_BOOL_RET,IsThreadpoolThread, ThreadBaseObject* thread); static FCDECL1(void, SetIsThreadpoolThread, ThreadBaseObject* thread); @@ -79,10 +75,13 @@ friend class ThreadBaseObject; extern "C" void QCALLTYPE ThreadNative_Start(QCall::ThreadHandle thread, int threadStackSize, int priority, PCWSTR pThreadName); extern "C" void QCALLTYPE ThreadNative_SetPriority(QCall::ObjectHandleOnStack thread, INT32 iPriority); +extern "C" void QCALLTYPE ThreadNative_GetCurrentThread(QCall::ObjectHandleOnStack thread); extern "C" void QCALLTYPE ThreadNative_SetIsBackground(QCall::ThreadHandle thread, BOOL value); extern "C" void QCALLTYPE ThreadNative_InformThreadNameChange(QCall::ThreadHandle thread, LPCWSTR name, INT32 len); extern "C" BOOL QCALLTYPE ThreadNative_YieldThread(); extern "C" UINT64 QCALLTYPE ThreadNative_GetCurrentOSThreadId(); +extern "C" void QCALLTYPE ThreadNative_Initialize(QCall::ObjectHandleOnStack t); +extern "C" INT32 QCALLTYPE ThreadNative_GetThreadState(QCall::ThreadHandle thread); #ifdef FEATURE_COMINTEROP_APARTMENT_SUPPORT extern "C" INT32 QCALLTYPE ThreadNative_GetApartmentState(QCall::ObjectHandleOnStack t); diff --git a/src/coreclr/vm/comwaithandle.cpp b/src/coreclr/vm/comwaithandle.cpp index b43e255068bb5..e80675cc03feb 100644 --- a/src/coreclr/vm/comwaithandle.cpp +++ b/src/coreclr/vm/comwaithandle.cpp @@ -11,106 +11,93 @@ ** ===========================================================*/ #include "common.h" -#include "object.h" -#include "field.h" -#include "excep.h" #include "comwaithandle.h" -FCIMPL3(INT32, WaitHandleNative::CorWaitOneNative, HANDLE handle, INT32 timeout, FC_BOOL_ARG useTrivialWaits) +extern "C" INT32 QCALLTYPE WaitHandle_WaitOneCore(HANDLE handle, INT32 timeout, BOOL useTrivialWaits) { - FCALL_CONTRACT; + QCALL_CONTRACT; INT32 retVal = 0; - HELPER_METHOD_FRAME_BEGIN_RET_0(); + + BEGIN_QCALL; _ASSERTE(handle != 0); _ASSERTE(handle != INVALID_HANDLE_VALUE); Thread* pThread = GET_THREAD(); - - WaitMode waitMode = (WaitMode)((!FC_ACCESS_BOOL(useTrivialWaits) ? WaitMode_Alertable : WaitMode_None) | WaitMode_IgnoreSyncCtx); + WaitMode waitMode = (WaitMode)((!useTrivialWaits ? WaitMode_Alertable : WaitMode_None) | WaitMode_IgnoreSyncCtx); retVal = pThread->DoAppropriateWait(1, &handle, TRUE, timeout, waitMode); - HELPER_METHOD_FRAME_END(); + END_QCALL; return retVal; } -FCIMPLEND -#ifdef TARGET_UNIX -extern "C" INT32 QCALLTYPE WaitHandle_CorWaitOnePrioritizedNative(HANDLE handle, INT32 timeoutMs) +extern "C" INT32 QCALLTYPE WaitHandle_WaitMultipleIgnoringSyncContext(HANDLE *handleArray, INT32 numHandles, BOOL waitForAll, INT32 timeout) { QCALL_CONTRACT; - DWORD result = WAIT_FAILED; - - BEGIN_QCALL; - - _ASSERTE(handle != NULL); - _ASSERTE(handle != INVALID_HANDLE_VALUE); - - result = PAL_WaitForSingleObjectPrioritized(handle, timeoutMs); - - END_QCALL; - return (INT32)result; -} -#endif - -FCIMPL4(INT32, WaitHandleNative::CorWaitMultipleNative, HANDLE *handleArray, INT32 numHandles, FC_BOOL_ARG waitForAll, INT32 timeout) -{ - FCALL_CONTRACT; - INT32 ret = 0; - HELPER_METHOD_FRAME_BEGIN_RET_0(); + BEGIN_QCALL; Thread * pThread = GET_THREAD(); #ifdef FEATURE_COMINTEROP_APARTMENT_SUPPORT // There are some issues with wait-all from an STA thread // - https://github.com/dotnet/runtime/issues/10243#issuecomment-385117537 - if (FC_ACCESS_BOOL(waitForAll) && numHandles > 1 && pThread->GetApartment() == Thread::AS_InSTA) + if (waitForAll && numHandles > 1 && pThread->GetApartment() == Thread::AS_InSTA) { COMPlusThrow(kNotSupportedException, W("NotSupported_WaitAllSTAThread")); } #endif // FEATURE_COMINTEROP_APARTMENT_SUPPORT - ret = pThread->DoAppropriateWait(numHandles, handleArray, FC_ACCESS_BOOL(waitForAll), timeout, (WaitMode)(WaitMode_Alertable | WaitMode_IgnoreSyncCtx)); + ret = pThread->DoAppropriateWait(numHandles, handleArray, waitForAll, timeout, (WaitMode)(WaitMode_Alertable | WaitMode_IgnoreSyncCtx)); - HELPER_METHOD_FRAME_END(); + END_QCALL; return ret; } -FCIMPLEND -FCIMPL3(INT32, WaitHandleNative::CorSignalAndWaitOneNative, HANDLE waitHandleSignalUNSAFE, HANDLE waitHandleWaitUNSAFE, INT32 timeout) +extern "C" INT32 QCALLTYPE WaitHandle_SignalAndWait(HANDLE waitHandleSignal, HANDLE waitHandleWait, INT32 timeout) { - FCALL_CONTRACT; + QCALL_CONTRACT; - INT32 retVal = 0; + INT32 retVal = (DWORD)-1; - HELPER_METHOD_FRAME_BEGIN_RET_0(); + BEGIN_QCALL; - _ASSERTE(waitHandleSignalUNSAFE != 0); - _ASSERTE(waitHandleWaitUNSAFE != 0); + _ASSERTE(waitHandleSignal != 0); + _ASSERTE(waitHandleWait != 0); Thread* pThread = GET_THREAD(); -#ifdef FEATURE_COMINTEROP - if (pThread->GetApartment() == Thread::AS_InSTA) { - COMPlusThrow(kNotSupportedException, W("NotSupported_SignalAndWaitSTAThread")); // Change this message - } -#endif - - DWORD res = (DWORD) -1; - - HANDLE handles[2]; - handles[0] = waitHandleSignalUNSAFE; - handles[1] = waitHandleWaitUNSAFE; +#ifdef FEATURE_COMINTEROP_APARTMENT_SUPPORT + if (pThread->GetApartment() == Thread::AS_InSTA) { - res = pThread->DoSignalAndWait(handles, timeout, TRUE /*alertable*/); + COMPlusThrow(kNotSupportedException, W("NotSupported_SignalAndWaitSTAThread")); } +#endif // FEATURE_COMINTEROP_APARTMENT_SUPPORT - retVal = res; + HANDLE handles[] = { waitHandleSignal, waitHandleWait }; + retVal = pThread->DoSignalAndWait(handles, timeout, TRUE /*alertable*/); - HELPER_METHOD_FRAME_END(); + END_QCALL; return retVal; } -FCIMPLEND + +#ifdef TARGET_UNIX +extern "C" INT32 QCALLTYPE WaitHandle_WaitOnePrioritized(HANDLE handle, INT32 timeoutMs) +{ + QCALL_CONTRACT; + + DWORD result = WAIT_FAILED; + + BEGIN_QCALL; + + _ASSERTE(handle != NULL); + _ASSERTE(handle != INVALID_HANDLE_VALUE); + + result = PAL_WaitForSingleObjectPrioritized(handle, timeoutMs); + + END_QCALL; + return (INT32)result; +} +#endif // TARGET_UNIX diff --git a/src/coreclr/vm/comwaithandle.h b/src/coreclr/vm/comwaithandle.h index d0af3076bf1c4..ac60538912913 100644 --- a/src/coreclr/vm/comwaithandle.h +++ b/src/coreclr/vm/comwaithandle.h @@ -14,15 +14,12 @@ #ifndef _COM_WAITABLE_HANDLE_H #define _COM_WAITABLE_HANDLE_H +extern "C" INT32 QCALLTYPE WaitHandle_WaitOneCore(HANDLE handle, INT32 timeout, BOOL useTrivialWaits); +extern "C" INT32 QCALLTYPE WaitHandle_WaitMultipleIgnoringSyncContext(HANDLE *handleArray, INT32 numHandles, BOOL waitForAll, INT32 timeout); +extern "C" INT32 QCALLTYPE WaitHandle_SignalAndWait(HANDLE waitHandleSignal, HANDLE waitHandleWait, INT32 timeout); -class WaitHandleNative -{ -public: - static FCDECL3(INT32, CorWaitOneNative, HANDLE handle, INT32 timeout, FC_BOOL_ARG useTrivialWaits); - static FCDECL4(INT32, CorWaitMultipleNative, HANDLE *handleArray, INT32 numHandles, FC_BOOL_ARG waitForAll, INT32 timeout); - static FCDECL3(INT32, CorSignalAndWaitOneNative, HANDLE waitHandleSignalUNSAFE, HANDLE waitHandleWaitUNSAFE, INT32 timeout); -}; #ifdef TARGET_UNIX -extern "C" INT32 QCALLTYPE WaitHandle_CorWaitOnePrioritizedNative(HANDLE handle, INT32 timeoutMs); -#endif -#endif +extern "C" INT32 QCALLTYPE WaitHandle_WaitOnePrioritized(HANDLE handle, INT32 timeoutMs); +#endif // TARGET_UNIX + +#endif // _COM_WAITABLE_HANDLE_H diff --git a/src/coreclr/vm/corhost.cpp b/src/coreclr/vm/corhost.cpp index 35c724e10a9ca..990eb02b00dc8 100644 --- a/src/coreclr/vm/corhost.cpp +++ b/src/coreclr/vm/corhost.cpp @@ -559,11 +559,11 @@ HRESULT CorHost2::CreateAppDomainWithManager( BEGIN_EXTERNAL_ENTRYPOINT(&hr); - AppDomain* pDomain = SystemDomain::System()->DefaultDomain(); + AppDomain* pDomain = AppDomain::GetCurrentDomain(); pDomain->SetFriendlyName(wszFriendlyName); - ETW::LoaderLog::DomainLoad(pDomain, (LPWSTR)wszFriendlyName); + ETW::LoaderLog::DomainLoad((LPWSTR)wszFriendlyName); if (dwFlags & APPDOMAIN_IGNORE_UNHANDLED_EXCEPTIONS) pDomain->SetIgnoreUnhandledExceptions(); diff --git a/src/coreclr/vm/domainassembly.cpp b/src/coreclr/vm/domainassembly.cpp index 5827236697166..64fb98569f10f 100644 --- a/src/coreclr/vm/domainassembly.cpp +++ b/src/coreclr/vm/domainassembly.cpp @@ -56,7 +56,6 @@ DomainAssembly::DomainAssembly(PEAssembly* pPEAssembly, LoaderAllocator* pLoader // Create the Assembly NewHolder assembly = Assembly::Create(GetPEAssembly(), GetDebuggerInfoBits(), IsCollectible(), memTracker, IsCollectible() ? GetLoaderAllocator() : NULL); - assembly->SetIsTenured(); m_pAssembly = assembly.Extract(); m_pModule = m_pAssembly->GetModule(); diff --git a/src/coreclr/vm/ecalllist.h b/src/coreclr/vm/ecalllist.h index 2b065fd338034..b1f475b3b1640 100644 --- a/src/coreclr/vm/ecalllist.h +++ b/src/coreclr/vm/ecalllist.h @@ -109,8 +109,8 @@ FCFuncStart(gCOMTypeHandleFuncs) FCFuncElement("GetFirstIntroducedMethod", RuntimeTypeHandle::GetFirstIntroducedMethod) FCFuncElement("GetNextIntroducedMethod", RuntimeTypeHandle::GetNextIntroducedMethod) FCFuncElement("GetCorElementType", RuntimeTypeHandle::GetCorElementType) - FCFuncElement("GetAssembly", RuntimeTypeHandle::GetAssembly) - FCFuncElement("GetModule", RuntimeTypeHandle::GetModule) + FCFuncElement("GetAssemblyIfExists", RuntimeTypeHandle::GetAssemblyIfExists) + FCFuncElement("GetModuleIfExists", RuntimeTypeHandle::GetModuleIfExists) FCFuncElement("GetBaseType", RuntimeTypeHandle::GetBaseType) FCFuncElement("GetElementType", RuntimeTypeHandle::GetElementType) FCFuncElement("GetArrayRank", RuntimeTypeHandle::GetArrayRank) @@ -222,7 +222,7 @@ FCFuncStart(gCOMModuleHandleFuncs) FCFuncEnd() FCFuncStart(gRuntimeAssemblyFuncs) - FCFuncElement("FCallIsDynamic", AssemblyNative::IsDynamic) + FCFuncElement("GetIsDynamic", AssemblyNative::GetIsDynamic) FCFuncElement("GetManifestModule", AssemblyHandle::GetManifestModule) FCFuncElement("GetToken", AssemblyHandle::GetToken) FCFuncEnd() @@ -298,14 +298,10 @@ FCFuncStart(gMathFFuncs) FCFuncEnd() FCFuncStart(gThreadFuncs) - FCFuncElement("Initialize", ThreadNative::Initialize) - FCFuncElement("GetCurrentThreadNative", ThreadNative::GetCurrentThread) FCFuncElement("InternalFinalize", ThreadNative::Finalize) - FCFuncElement("get_IsAlive", ThreadNative::IsAlive) FCFuncElement("GetIsBackground", ThreadNative::GetIsBackground) FCFuncElement("get_IsThreadPoolThread", ThreadNative::IsThreadpoolThread) FCFuncElement("set_IsThreadPoolThread", ThreadNative::SetIsThreadpoolThread) - FCFuncElement("GetThreadStateNative", ThreadNative::GetThreadState) FCFuncElement("get_OptimalMaxSpinWaitsPerSpinIteration", ThreadNative::GetOptimalMaxSpinWaitsPerSpinIteration) FCFuncEnd() @@ -313,12 +309,6 @@ FCFuncStart(gThreadPoolFuncs) FCFuncElement("GetNextConfigUInt32Value", ThreadPoolNative::GetNextConfigUInt32Value) FCFuncEnd() -FCFuncStart(gWaitHandleFuncs) - FCFuncElement("WaitOneCore", WaitHandleNative::CorWaitOneNative) - FCFuncElement("WaitMultipleIgnoringSyncContext", WaitHandleNative::CorWaitMultipleNative) - FCFuncElement("SignalAndWaitNative", WaitHandleNative::CorSignalAndWaitOneNative) -FCFuncEnd() - FCFuncStart(gCastHelpers) FCFuncElement("IsInstanceOfAny_NoCacheLookup", ::IsInstanceOfAny_NoCacheLookup) FCFuncElement("ChkCastAny_NoCacheLookup", ::ChkCastAny_NoCacheLookup) @@ -493,7 +483,6 @@ FCClassElement("Thread", "System.Threading", gThreadFuncs) FCClassElement("ThreadPool", "System.Threading", gThreadPoolFuncs) FCClassElement("Type", "System", gSystem_Type) FCClassElement("TypedReference", "System", gTypedReferenceFuncs) -FCClassElement("WaitHandle", "System.Threading", gWaitHandleFuncs) #undef FCFuncElement #undef FCFuncElementSig diff --git a/src/coreclr/vm/eventtrace.cpp b/src/coreclr/vm/eventtrace.cpp index 79c3043a24964..4f563dd5b2744 100644 --- a/src/coreclr/vm/eventtrace.cpp +++ b/src/coreclr/vm/eventtrace.cpp @@ -1926,7 +1926,7 @@ VOID ETW::EnumerationLog::ModuleRangeRundown() TRACE_LEVEL_INFORMATION, CLR_PERFTRACK_PRIVATE_KEYWORD)) { - ETW::EnumerationLog::EnumerationHelper(NULL, NULL, ETW::EnumerationLog::EnumerationStructs::ModuleRangeLoadPrivate); + ETW::EnumerationLog::EnumerationHelper(NULL, ETW::EnumerationLog::EnumerationStructs::ModuleRangeLoadPrivate); } } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); } @@ -2037,7 +2037,7 @@ VOID ETW::EnumerationLog::StartRundown() enumerationOptions |= ETW::EnumerationLog::EnumerationStructs::JittedMethodRichDebugInfo; } - ETW::EnumerationLog::EnumerationHelper(NULL, NULL, enumerationOptions); + ETW::EnumerationLog::EnumerationHelper(NULL, enumerationOptions); if (bIsThreadingRundownEnabled) { @@ -2124,9 +2124,8 @@ VOID ETW::EnumerationLog::EnumerateForCaptureState() { DWORD enumerationOptions = GetEnumerationOptionsFromRuntimeKeywords(); - // Send unload events for all remaining domains, including shared domain and - // default domain. - ETW::EnumerationLog::EnumerationHelper(NULL /* module filter */, NULL /* domain filter */, enumerationOptions); + // Send unload events for all remaining modules + ETW::EnumerationLog::EnumerationHelper(NULL /* module filter */, enumerationOptions); // Send thread created events for all currently active threads, if requested if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_DOTNET_Context, @@ -2227,7 +2226,7 @@ VOID ETW::EnumerationLog::EndRundown() enumerationOptions |= ETW::EnumerationLog::EnumerationStructs::JittedMethodRichDebugInfo; } - ETW::EnumerationLog::EnumerationHelper(NULL, NULL, enumerationOptions); + ETW::EnumerationLog::EnumerationHelper(NULL, enumerationOptions); if (bIsThreadingRundownEnabled) { @@ -2964,7 +2963,7 @@ VOID ETW::ExceptionLog::ExceptionFilterEnd() /****************************************************************************/ /* This is called by the runtime when a domain is loaded */ /****************************************************************************/ -VOID ETW::LoaderLog::DomainLoadReal(BaseDomain *pDomain, _In_opt_ LPWSTR wszFriendlyName) +VOID ETW::LoaderLog::DomainLoadReal(_In_opt_ LPWSTR wszFriendlyName) { CONTRACTL { NOTHROW; @@ -2978,7 +2977,7 @@ VOID ETW::LoaderLog::DomainLoadReal(BaseDomain *pDomain, _In_opt_ LPWSTR wszFrie CLR_LOADER_KEYWORD)) { DWORD dwEventOptions = ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleLoad; - ETW::LoaderLog::SendDomainEvent(pDomain, dwEventOptions, wszFriendlyName); + ETW::LoaderLog::SendDomainEvent(dwEventOptions, wszFriendlyName); } } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); } @@ -2986,7 +2985,7 @@ VOID ETW::LoaderLog::DomainLoadReal(BaseDomain *pDomain, _In_opt_ LPWSTR wszFrie /****************************************************************************/ /* This is called by the runtime when an AppDomain is unloaded */ /****************************************************************************/ -VOID ETW::LoaderLog::DomainUnload(AppDomain *pDomain) +VOID ETW::LoaderLog::DomainUnload() { CONTRACTL { NOTHROW; @@ -3009,7 +3008,7 @@ VOID ETW::LoaderLog::DomainUnload(AppDomain *pDomain) enumerationOptions |= ETW::EnumerationLog::EnumerationStructs::TypeUnload; } - ETW::EnumerationLog::EnumerationHelper(NULL, pDomain, enumerationOptions); + ETW::EnumerationLog::EnumerationHelper(NULL, enumerationOptions); } } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); } @@ -3873,7 +3872,7 @@ VOID ETW::LoaderLog::ModuleLoad(Module *pModule, LONG liReportedSharedModule) if(bTraceFlagLoaderSet || bTraceFlagPerfTrackSet) ETW::LoaderLog::SendModuleEvent(pModule, ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleLoad | ETW::EnumerationLog::EnumerationStructs::ModuleRangeLoad); - ETW::EnumerationLog::EnumerationHelper(pModule, NULL, enumerationOptions); + ETW::EnumerationLog::EnumerationHelper(pModule, enumerationOptions); } // we want to report domainmodule events whenever they are loaded in any AppDomain @@ -3910,9 +3909,8 @@ VOID ETW::EnumerationLog::ProcessShutdown() { DWORD enumerationOptions = GetEnumerationOptionsFromRuntimeKeywords(); - // Send unload events for all remaining domains, including shared domain and - // default domain. - ETW::EnumerationLog::EnumerationHelper(NULL /* module filter */, NULL /* domain filter */, enumerationOptions); + // Send unload events for all remaining modules + ETW::EnumerationLog::EnumerationHelper(NULL /* module filter */, enumerationOptions); } } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); } @@ -3926,20 +3924,20 @@ VOID ETW::EnumerationLog::ProcessShutdown() /****************************************************************************/ /* This routine is used to send a domain load/unload or rundown event */ /****************************************************************************/ -VOID ETW::LoaderLog::SendDomainEvent(BaseDomain *pBaseDomain, DWORD dwEventOptions, LPCWSTR wszFriendlyName) +VOID ETW::LoaderLog::SendDomainEvent(DWORD dwEventOptions, LPCWSTR wszFriendlyName) { CONTRACTL { THROWS; GC_TRIGGERS; + PRECONDITION(AppDomain::GetCurrentDomain() != NULL); } CONTRACTL_END; - if(!pBaseDomain) - return; + AppDomain* pDomain = AppDomain::GetCurrentDomain(); PCWSTR szDtraceOutput1=W(""); - BOOL bIsAppDomain = pBaseDomain->IsAppDomain(); + BOOL bIsAppDomain = TRUE; - ULONGLONG ullDomainId = (ULONGLONG)pBaseDomain; + ULONGLONG ullDomainId = (ULONGLONG)pDomain; ULONG ulDomainFlags = ETW::LoaderLog::LoaderStructs::DefaultDomain | ETW::LoaderLog::LoaderStructs::ExecutableDomain; LPCWSTR wsEmptyString = W(""); @@ -3949,7 +3947,7 @@ VOID ETW::LoaderLog::SendDomainEvent(BaseDomain *pBaseDomain, DWORD dwEventOptio if(wszFriendlyName) lpswzDomainName = (PWCHAR)wszFriendlyName; else - lpswzDomainName = (PWCHAR)pBaseDomain->AsAppDomain()->GetFriendlyName(); + lpswzDomainName = (PWCHAR)pDomain->GetFriendlyName(); /* prepare events args for ETW and ETM */ szDtraceOutput1 = (PCWSTR)lpswzDomainName; @@ -5238,12 +5236,9 @@ VOID ETW::MethodLog::SendEventsForJitMethodsHelper(LoaderAllocator *pLoaderAlloc /****************************************************************************/ /* This routine sends back method events of type 'dwEventOptions', for all JITed methods in either a given LoaderAllocator (if pLoaderAllocatorFilter is non NULL) - or in a given Domain (if pDomainFilter is non NULL) or for - all methods (if both filters are null) */ + or all methods (if pLoaderAllocatorFilter is null) */ /****************************************************************************/ -// Code review indicates this method is never called with both filters NULL. Ideally we would -// assert this and change the comment above, but given I am making a change late in the release I am being cautious -VOID ETW::MethodLog::SendEventsForJitMethods(BaseDomain *pDomainFilter, LoaderAllocator *pLoaderAllocatorFilter, DWORD dwEventOptions) +VOID ETW::MethodLog::SendEventsForJitMethods(BOOL getCodeVersionIds, LoaderAllocator *pLoaderAllocatorFilter, DWORD dwEventOptions) { CONTRACTL { NOTHROW; @@ -5303,9 +5298,8 @@ VOID ETW::MethodLog::SendEventsForJitMethods(BaseDomain *pDomainFilter, LoaderAl // table lock that corresponds to the domain or module we're currently iterating over. // - // We only support getting rejit IDs when filtering by domain. #ifdef FEATURE_CODE_VERSIONING - if (pDomainFilter) + if (getCodeVersionIds) { CodeVersionManager::LockHolder codeVersioningLockHolder; SendEventsForJitMethodsHelper( @@ -5337,21 +5331,24 @@ VOID ETW::MethodLog::SendEventsForJitMethods(BaseDomain *pDomainFilter, LoaderAl //--------------------------------------------------------------------------------------- // -// Wrapper around IterateDomain, which locks the AppDomain to be < -// STAGE_FINALIZED until the iteration is complete. +// This routine fires ETW events for +// Domain +// Assemblies in them +// Modules in them +// JIT methods in them +// R2R methods in them +// based on enumeration options // // Arguments: -// pAppDomain - AppDomain to iterate -// enumerationOptions - Flags indicating what to enumerate. Just passed -// straight through to IterateDomain +// enumerationOptions - Flags indicating what to enumerate. // -VOID ETW::EnumerationLog::IterateAppDomain(AppDomain * pAppDomain, DWORD enumerationOptions) +VOID ETW::EnumerationLog::IterateAppDomain(DWORD enumerationOptions) { CONTRACTL { THROWS; GC_TRIGGERS; - PRECONDITION(pAppDomain != NULL); + PRECONDITION(AppDomain::GetCurrentDomain() != NULL); } CONTRACTL_END; @@ -5359,54 +5356,22 @@ VOID ETW::EnumerationLog::IterateAppDomain(AppDomain * pAppDomain, DWORD enumera // ensure the App Domain does not get finalized until we're all done SystemDomain::LockHolder lh; - // Now it's safe to do the iteration - IterateDomain(pAppDomain, enumerationOptions); -} - -/********************************************************************************/ -/* This routine fires ETW events for - Domain, - Assemblies in them, - DomainModule's in them, - Modules in them, - JIT methods in them, - and the NGEN methods in them - based on enumerationOptions.*/ -/********************************************************************************/ -VOID ETW::EnumerationLog::IterateDomain(BaseDomain *pDomain, DWORD enumerationOptions) -{ - CONTRACTL { - THROWS; - GC_TRIGGERS; - PRECONDITION(pDomain != NULL); - } CONTRACTL_END; - -#if defined(_DEBUG) && !defined(DACCESS_COMPILE) - // Do not call IterateDomain() directly with an AppDomain. Use - // IterateAppDomain(), which wraps this function with a hold on the - // SystemDomain lock, which ensures pDomain's type data doesn't disappear - // on us. - if (pDomain->IsAppDomain()) - { - _ASSERTE(SystemDomain::IsUnderDomainLock()); - } -#endif // defined(_DEBUG) && !defined(DACCESS_COMPILE) - + AppDomain* pDomain = AppDomain::GetCurrentDomain(); EX_TRY { // DC Start events for Domain if(enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) { - ETW::LoaderLog::SendDomainEvent(pDomain, enumerationOptions); + ETW::LoaderLog::SendDomainEvent(enumerationOptions); } // DC End or Unload Jit Method events if (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodUnloadOrDCEndAny) { - ETW::MethodLog::SendEventsForJitMethods(pDomain, NULL, enumerationOptions); + ETW::MethodLog::SendEventsForJitMethods(TRUE /*getCodeVersionIds*/, NULL, enumerationOptions); } - AppDomain::AssemblyIterator assemblyIterator = pDomain->AsAppDomain()->IterateAssembliesEx( + AppDomain::AssemblyIterator assemblyIterator = pDomain->IterateAssembliesEx( (AssemblyIterationFlags)(kIncludeLoaded | kIncludeExecution)); CollectibleAssemblyHolder pDomainAssembly; while (assemblyIterator.Next(pDomainAssembly.This())) @@ -5430,14 +5395,14 @@ VOID ETW::EnumerationLog::IterateDomain(BaseDomain *pDomain, DWORD enumerationOp // DC Start or Load Jit Method events if (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodLoadOrDCStartAny) { - ETW::MethodLog::SendEventsForJitMethods(pDomain, NULL, enumerationOptions); + ETW::MethodLog::SendEventsForJitMethods(TRUE /*getCodeVersionIds*/, NULL, enumerationOptions); } // DC End or Unload events for Domain if((enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) || (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload)) { - ETW::LoaderLog::SendDomainEvent(pDomain, enumerationOptions); + ETW::LoaderLog::SendDomainEvent(enumerationOptions); } } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); } @@ -5465,7 +5430,7 @@ VOID ETW::EnumerationLog::IterateCollectibleLoaderAllocator(AssemblyLoaderAlloca // Unload Jit Method events if (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodUnload) { - ETW::MethodLog::SendEventsForJitMethods(NULL, pLoaderAllocator, enumerationOptions); + ETW::MethodLog::SendEventsForJitMethods(FALSE /*getCodeVersionIds*/, pLoaderAllocator, enumerationOptions); } // Iterate on all DomainAssembly loaded from the same AssemblyLoaderAllocator @@ -5488,7 +5453,7 @@ VOID ETW::EnumerationLog::IterateCollectibleLoaderAllocator(AssemblyLoaderAlloca // Load Jit Method events if (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodLoad) { - ETW::MethodLog::SendEventsForJitMethods(NULL, pLoaderAllocator, enumerationOptions); + ETW::MethodLog::SendEventsForJitMethods(FALSE /*getCodeVersionIds*/, pLoaderAllocator, enumerationOptions); } } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); } @@ -5593,17 +5558,12 @@ VOID ETW::EnumerationLog::IterateModule(Module *pModule, DWORD enumerationOption // // Arguments: // * moduleFilter - if non-NULL, events from only moduleFilter module are reported -// * domainFilter - if non-NULL, events from only domainFilter domain are reported // * enumerationOptions - Flags from ETW::EnumerationLog::EnumerationStructs which // describe which events should be sent. // -// Notes: -// * if all filter args are NULL, events from all domains are reported -// -// // static -VOID ETW::EnumerationLog::EnumerationHelper(Module *moduleFilter, BaseDomain *domainFilter, DWORD enumerationOptions) +VOID ETW::EnumerationLog::EnumerationHelper(Module *moduleFilter, DWORD enumerationOptions) { CONTRACTL { THROWS; @@ -5625,36 +5585,18 @@ VOID ETW::EnumerationLog::EnumerationHelper(Module *moduleFilter, BaseDomain *do // DC End or Unload Jit Method events from all Domains if (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodUnloadOrDCEndAny) { - ETW::MethodLog::SendEventsForJitMethods(NULL, NULL, enumerationOptions); + ETW::MethodLog::SendEventsForJitMethods(FALSE /*getCodeVersionIds*/, NULL, enumerationOptions); } // DC Start or Load Jit Method events from all Domains if (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodLoadOrDCStartAny) { - ETW::MethodLog::SendEventsForJitMethods(NULL, NULL, enumerationOptions); + ETW::MethodLog::SendEventsForJitMethods(FALSE /*getCodeVersionIds*/, NULL, enumerationOptions); } } else { - if(domainFilter) - { - if(domainFilter->IsAppDomain()) - { - ETW::EnumerationLog::IterateAppDomain(domainFilter->AsAppDomain(), enumerationOptions); - } - else - { - ETW::EnumerationLog::IterateDomain(domainFilter, enumerationOptions); - } - } - else - { - AppDomain *pDomain = AppDomain::GetCurrentDomain(); - if (pDomain != NULL) - { - ETW::EnumerationLog::IterateAppDomain(pDomain, enumerationOptions); - } - } + ETW::EnumerationLog::IterateAppDomain(enumerationOptions); } } diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index b9d260cfe7830..9e26592648170 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -3476,49 +3476,7 @@ size_t CEEInfo::printClassName(CORINFO_CLASS_HANDLE cls, char* buffer, size_t bu } /*********************************************************************/ -CORINFO_MODULE_HANDLE CEEInfo::getClassModule(CORINFO_CLASS_HANDLE clsHnd) -{ - CONTRACTL { - NOTHROW; - GC_NOTRIGGER; - MODE_PREEMPTIVE; - } CONTRACTL_END; - - CORINFO_MODULE_HANDLE result = NULL; - - JIT_TO_EE_TRANSITION_LEAF(); - - TypeHandle VMClsHnd(clsHnd); - - result = CORINFO_MODULE_HANDLE(VMClsHnd.GetModule()); - - EE_TO_JIT_TRANSITION_LEAF(); - - return result; -} - -/*********************************************************************/ -CORINFO_ASSEMBLY_HANDLE CEEInfo::getModuleAssembly(CORINFO_MODULE_HANDLE modHnd) -{ - CONTRACTL { - NOTHROW; - GC_NOTRIGGER; - MODE_PREEMPTIVE; - } CONTRACTL_END; - - CORINFO_ASSEMBLY_HANDLE result = NULL; - - JIT_TO_EE_TRANSITION_LEAF(); - - result = CORINFO_ASSEMBLY_HANDLE(GetModule(modHnd)->GetAssembly()); - - EE_TO_JIT_TRANSITION_LEAF(); - - return result; -} - -/*********************************************************************/ -const char* CEEInfo::getAssemblyName(CORINFO_ASSEMBLY_HANDLE asmHnd) +const char* CEEInfo::getClassAssemblyName(CORINFO_CLASS_HANDLE clsHnd) { CONTRACTL { THROWS; @@ -3526,10 +3484,11 @@ const char* CEEInfo::getAssemblyName(CORINFO_ASSEMBLY_HANDLE asmHnd) MODE_PREEMPTIVE; } CONTRACTL_END; - const char* result = NULL; + const char* result = NULL; JIT_TO_EE_TRANSITION(); - result = ((Assembly*)asmHnd)->GetSimpleName(); + TypeHandle th(clsHnd); + result = th.GetAssembly()->GetSimpleName(); EE_TO_JIT_TRANSITION(); return result; diff --git a/src/coreclr/vm/loaderallocator.cpp b/src/coreclr/vm/loaderallocator.cpp index ff6506b76292a..dde9db0f76a00 100644 --- a/src/coreclr/vm/loaderallocator.cpp +++ b/src/coreclr/vm/loaderallocator.cpp @@ -62,7 +62,6 @@ LoaderAllocator::LoaderAllocator(bool collectible) : m_fUnloaded = false; m_fMarked = false; m_pLoaderAllocatorDestroyNext = NULL; - m_pDomain = NULL; m_pCodeHeapInitialAlloc = NULL; m_pVSDHeapInitialAlloc = NULL; m_pLastUsedCodeHeap = NULL; @@ -506,13 +505,16 @@ void LoaderAllocator::GCLoaderAllocators(LoaderAllocator* pOriginalLoaderAllocat THROWS; GC_TRIGGERS; MODE_PREEMPTIVE; + PRECONDITION(pOriginalLoaderAllocator != NULL); + PRECONDITION(pOriginalLoaderAllocator->IsCollectible()); + PRECONDITION(pOriginalLoaderAllocator->Id()->GetType() == LAT_Assembly); } CONTRACTL_END; // List of LoaderAllocators being deleted LoaderAllocator * pFirstDestroyedLoaderAllocator = NULL; - AppDomain* pAppDomain = (AppDomain*)pOriginalLoaderAllocator->GetDomain(); + AppDomain* pAppDomain = AppDomain::GetCurrentDomain(); // Collect all LoaderAllocators that don't have anymore DomainAssemblies alive // Note: that it may not collect our pOriginalLoaderAllocator in case this @@ -1059,12 +1061,10 @@ void LoaderAllocator::ActivateManagedTracking() #define COLLECTIBLE_CODEHEAP_SIZE (10 * GetOsPageSize()) #define COLLECTIBLE_VIRTUALSTUBDISPATCH_HEAP_SPACE (2 * GetOsPageSize()) -void LoaderAllocator::Init(BaseDomain *pDomain, BYTE *pExecutableHeapMemory) +void LoaderAllocator::Init(BYTE *pExecutableHeapMemory) { STANDARD_VM_CONTRACT; - m_pDomain = pDomain; - m_crstLoaderAllocator.Init(CrstLoaderAllocator, (CrstFlags)CRST_UNSAFE_COOPGC); m_crstLoaderAllocatorHandleTable.Init(CrstLeafLock, (CrstFlags)CRST_UNSAFE_COOPGC); m_InteropDataCrst.Init(CrstInteropData, CRST_REENTRANCY); @@ -1446,7 +1446,6 @@ void LoaderAllocator::Terminate() m_pFuncPtrStubs = NULL; } - // This was the block reserved by BaseDomain::Init for the loaderheaps. if (m_InitialReservedMemForLoaderHeaps) { ExecutableAllocator::Instance()->Release(m_InitialReservedMemForLoaderHeaps); @@ -1725,7 +1724,7 @@ void DomainAssemblyIterator::operator++() #ifndef DACCESS_COMPILE -void AssemblyLoaderAllocator::Init(AppDomain* pAppDomain) +void AssemblyLoaderAllocator::Init() { m_Id.Init(); @@ -1733,7 +1732,7 @@ void AssemblyLoaderAllocator::Init(AppDomain* pAppDomain) // GC mode, in case the caller requires that m_dependentHandleToNativeObjectSetCrst.Init(CrstLeafLock, CRST_UNSAFE_ANYMODE); - LoaderAllocator::Init((BaseDomain *)pAppDomain); + LoaderAllocator::Init(NULL /*pExecutableHeapMemory*/); if (IsCollectible()) { // TODO: the ShuffleThunkCache should really be using the m_pStubHeap, however the unloadability support @@ -1933,10 +1932,11 @@ void AssemblyLoaderAllocator::CleanupHandles() NOTHROW; MODE_ANY; CAN_TAKE_LOCK; + PRECONDITION(IsCollectible()); + PRECONDITION(Id()->GetType() == LAT_Assembly); } CONTRACTL_END; - _ASSERTE(GetDomain()->IsAppDomain()); if (m_hLoaderAllocatorObjectHandle != NULL) { @@ -2058,12 +2058,12 @@ void LoaderAllocator::CleanupFailedTypeInit() return; } - _ASSERTE(GetDomain()->IsAppDomain()); + _ASSERTE(Id()->GetType() == LAT_Assembly); // This method doesn't take a lock around loader allocator state access, because // it's supposed to be called only during cleanup. However, the domain-level state // might be accessed by multiple threads. - ListLock *pLock = ((AppDomain*)GetDomain())->GetClassInitLock(); + ListLock *pLock = AppDomain::GetCurrentDomain()->GetClassInitLock(); while (!m_failedTypeInitCleanupList.IsEmpty()) { diff --git a/src/coreclr/vm/loaderallocator.hpp b/src/coreclr/vm/loaderallocator.hpp index 82f24813cb8d1..2bce73a85cc24 100644 --- a/src/coreclr/vm/loaderallocator.hpp +++ b/src/coreclr/vm/loaderallocator.hpp @@ -264,6 +264,8 @@ class SegmentedHandleIndexStack public: + ~SegmentedHandleIndexStack(); + // Push the value to the stack. If the push cannot be done due to OOM, return false; inline bool Push(DWORD value); @@ -360,8 +362,6 @@ class LoaderAllocator BYTE *GetVSDHeapInitialBlock(DWORD *pSize); BYTE *GetCodeHeapInitialBlock(const BYTE * loAddr, const BYTE * hiAddr, DWORD minimumSize, DWORD *pSize); - BaseDomain *m_pDomain; - // ExecutionManager caches void * m_pLastUsedCodeHeap; void * m_pLastUsedDynamicCodeHeap; @@ -735,9 +735,8 @@ class LoaderAllocator LoaderAllocator(bool collectible); virtual ~LoaderAllocator(); - BaseDomain *GetDomain() { LIMITED_METHOD_CONTRACT; return m_pDomain; } virtual BOOL CanUnload() = 0; - void Init(BaseDomain *pDomain, BYTE *pExecutableHeapMemory = NULL); + void Init(BYTE *pExecutableHeapMemory); void Terminate(); virtual void ReleaseManagedAssemblyLoadContext() {} @@ -887,7 +886,7 @@ class GlobalLoaderAllocator : public LoaderAllocator LoaderAllocatorID m_Id; public: - void Init(BaseDomain *pDomain); + void Init(); GlobalLoaderAllocator() : LoaderAllocator(false), m_Id(LAT_Global, (void*)1) { LIMITED_METHOD_CONTRACT;}; virtual LoaderAllocatorID* Id(); virtual BOOL CanUnload(); @@ -913,7 +912,7 @@ class AssemblyLoaderAllocator : public LoaderAllocator , m_binderToRelease(NULL) #endif { LIMITED_METHOD_CONTRACT; } - void Init(AppDomain *pAppDomain); + void Init(); virtual BOOL CanUnload(); void AddDomainAssembly(DomainAssembly *pDomainAssembly) diff --git a/src/coreclr/vm/loaderallocator.inl b/src/coreclr/vm/loaderallocator.inl index d839a4632277f..374e19902fd32 100644 --- a/src/coreclr/vm/loaderallocator.inl +++ b/src/coreclr/vm/loaderallocator.inl @@ -24,9 +24,9 @@ inline bool LoaderAllocator::IsExposedObjectLive() return !ObjectHandleIsNull(m_hLoaderAllocatorObjectHandle); } -inline void GlobalLoaderAllocator::Init(BaseDomain *pDomain) +inline void GlobalLoaderAllocator::Init() { - LoaderAllocator::Init(pDomain, m_ExecutableHeapInstance); + LoaderAllocator::Init(m_ExecutableHeapInstance); } inline BOOL LoaderAllocatorID::Equals(LoaderAllocatorID *pId) @@ -208,6 +208,19 @@ inline DWORD SegmentedHandleIndexStack::Pop() return m_TOSSegment->m_data[--m_TOSIndex]; } +inline SegmentedHandleIndexStack::~SegmentedHandleIndexStack() +{ + LIMITED_METHOD_CONTRACT; + + while (m_TOSSegment != NULL) + { + Segment* prevSegment = m_TOSSegment->m_prev; + delete m_TOSSegment; + m_TOSSegment = prevSegment; + } + m_freeSegment = NULL; +} + inline bool SegmentedHandleIndexStack::IsEmpty() { LIMITED_METHOD_CONTRACT; diff --git a/src/coreclr/vm/object.h b/src/coreclr/vm/object.h index 1afd632dea09e..6c17bf93c800e 100644 --- a/src/coreclr/vm/object.h +++ b/src/coreclr/vm/object.h @@ -1219,13 +1219,6 @@ class ReflectModuleBaseObject : public Object } }; -NOINLINE ReflectModuleBaseObject* GetRuntimeModuleHelper(LPVOID __me, Module *pModule, OBJECTREF keepAlive); -#define FC_RETURN_MODULE_OBJECT(pModule, refKeepAlive) FC_INNER_RETURN(ReflectModuleBaseObject*, GetRuntimeModuleHelper(__me, pModule, refKeepAlive)) - - - - - class ThreadBaseObject; class SynchronizationContextObject: public Object { @@ -1302,7 +1295,6 @@ typedef DPTR(class ThreadBaseObject) PTR_ThreadBaseObject; class ThreadBaseObject : public Object { friend class ClrDataAccess; - friend class ThreadNative; friend class CoreLibBinder; friend class Object; @@ -1439,8 +1431,6 @@ class AssemblyBaseObject : public Object SetObjectReference(&m_pSyncRoot, pSyncRoot); } }; -NOINLINE AssemblyBaseObject* GetRuntimeAssemblyHelper(LPVOID __me, Assembly *pAssembly, OBJECTREF keepAlive); -#define FC_RETURN_ASSEMBLY_OBJECT(pAssembly, refKeepAlive) FC_INNER_RETURN(AssemblyBaseObject*, GetRuntimeAssemblyHelper(__me, pAssembly, refKeepAlive)) // AssemblyLoadContextBaseObject // This class is the base class for AssemblyLoadContext diff --git a/src/coreclr/vm/proftoeeinterfaceimpl.cpp b/src/coreclr/vm/proftoeeinterfaceimpl.cpp index e99273beb5d13..614a6036fdf8a 100644 --- a/src/coreclr/vm/proftoeeinterfaceimpl.cpp +++ b/src/coreclr/vm/proftoeeinterfaceimpl.cpp @@ -3148,9 +3148,9 @@ HRESULT ProfToEEInterfaceImpl::GetAppDomainStaticAddress(ClassID classId, return E_INVALIDARG; } - // Some domains, like the system domain, aren't APP domains, and thus don't contain any + // The system domain isn't an APP domain and thus doesn't contain any // statics. See if the profiler is trying to be naughty. - if (!((BaseDomain*) appDomainId)->IsAppDomain()) + if (appDomainId == (AppDomainID)SystemDomain::System()) { return E_INVALIDARG; } @@ -3382,9 +3382,9 @@ HRESULT ProfToEEInterfaceImpl::GetThreadStaticAddress2(ClassID classId, return E_INVALIDARG; } - // Some domains, like the system domain, aren't APP domains, and thus don't contain any + // The system domain isn't an APP domain and thus doesn't contain any // statics. See if the profiler is trying to be naughty. - if (!((BaseDomain*) appDomainId)->IsAppDomain()) + if (appDomainId == (AppDomainID)SystemDomain::System()) { return E_INVALIDARG; } @@ -5479,25 +5479,8 @@ HRESULT ProfToEEInterfaceImpl::GetAppDomainInfo(AppDomainID appDomainId, return E_INVALIDARG; } - BaseDomain *pDomain; // Internal data structure. HRESULT hr = S_OK; - // @todo: - // Right now, this ID is not a true AppDomain, since we use the old - // AppDomain/SystemDomain model in the profiling API. This means that - // the profiler exposes the SharedDomain and the SystemDomain to the - // outside world. It's not clear whether this is actually the right thing - // to do or not. - seantrow - // - // Postponed to V2. - // - - pDomain = (BaseDomain *) appDomainId; - - // Make sure they've passed in a valid appDomainId - if (pDomain == NULL) - return (E_INVALIDARG); - // Pick sensible defaults. if (pcchName) *pcchName = 0; @@ -5507,10 +5490,10 @@ HRESULT ProfToEEInterfaceImpl::GetAppDomainInfo(AppDomainID appDomainId, *pProcessId = 0; LPCWSTR szFriendlyName; - if (pDomain == SystemDomain::System()) + if (appDomainId == (AppDomainID)SystemDomain::System()) szFriendlyName = g_pwBaseLibrary; else - szFriendlyName = ((AppDomain*)pDomain)->GetFriendlyNameForDebugger(); + szFriendlyName = ((AppDomain*)appDomainId)->GetFriendlyNameForDebugger(); if (szFriendlyName != NULL) { diff --git a/src/coreclr/vm/qcallentrypoints.cpp b/src/coreclr/vm/qcallentrypoints.cpp index 2d2345ca214c1..4181a027e669c 100644 --- a/src/coreclr/vm/qcallentrypoints.cpp +++ b/src/coreclr/vm/qcallentrypoints.cpp @@ -118,6 +118,8 @@ static const Entry s_QCall[] = DllImportEntry(RuntimeTypeHandle_MakeArray) DllImportEntry(RuntimeTypeHandle_IsCollectible) DllImportEntry(RuntimeTypeHandle_GetConstraints) + DllImportEntry(RuntimeTypeHandle_GetAssemblySlow) + DllImportEntry(RuntimeTypeHandle_GetModuleSlow) DllImportEntry(RuntimeTypeHandle_GetNumVirtualsAndStaticVirtuals) DllImportEntry(RuntimeTypeHandle_VerifyInterfaceIsImplemented) DllImportEntry(RuntimeTypeHandle_GetInterfaceMethodImplementation) @@ -158,6 +160,7 @@ static const Entry s_QCall[] = DllImportEntry(ModuleHandle_ResolveMethod) DllImportEntry(ModuleHandle_ResolveField) DllImportEntry(ModuleHandle_GetPEKind) + DllImportEntry(AssemblyHandle_GetManifestModuleSlow) DllImportEntry(TypeBuilder_DefineGenericParam) DllImportEntry(TypeBuilder_DefineType) DllImportEntry(TypeBuilder_SetParentType) @@ -235,10 +238,13 @@ static const Entry s_QCall[] = DllImportEntry(AppDomain_CreateDynamicAssembly) DllImportEntry(ThreadNative_Start) DllImportEntry(ThreadNative_SetPriority) + DllImportEntry(ThreadNative_GetCurrentThread) DllImportEntry(ThreadNative_SetIsBackground) DllImportEntry(ThreadNative_InformThreadNameChange) DllImportEntry(ThreadNative_YieldThread) DllImportEntry(ThreadNative_GetCurrentOSThreadId) + DllImportEntry(ThreadNative_Initialize) + DllImportEntry(ThreadNative_GetThreadState) #ifdef FEATURE_COMINTEROP_APARTMENT_SUPPORT DllImportEntry(ThreadNative_GetApartmentState) DllImportEntry(ThreadNative_SetApartmentState) @@ -252,9 +258,12 @@ static const Entry s_QCall[] = #ifdef FEATURE_COMINTEROP DllImportEntry(ThreadNative_DisableComObjectEagerCleanup) #endif // FEATURE_COMINTEROP + DllImportEntry(WaitHandle_WaitOneCore) + DllImportEntry(WaitHandle_WaitMultipleIgnoringSyncContext) + DllImportEntry(WaitHandle_SignalAndWait) #ifdef TARGET_UNIX - DllImportEntry(WaitHandle_CorWaitOnePrioritizedNative) -#endif + DllImportEntry(WaitHandle_WaitOnePrioritized) +#endif // TARGET_UNIX DllImportEntry(ClrConfig_GetConfigBoolValue) DllImportEntry(Buffer_Clear) DllImportEntry(Buffer_MemMove) diff --git a/src/coreclr/vm/runtimehandles.cpp b/src/coreclr/vm/runtimehandles.cpp index dca024a0d7b5c..7b067cf8103af 100644 --- a/src/coreclr/vm/runtimehandles.cpp +++ b/src/coreclr/vm/runtimehandles.cpp @@ -161,43 +161,6 @@ NOINLINE static ReflectClassBaseObject* GetRuntimeTypeHelper(LPVOID __me, TypeHa #define RETURN_CLASS_OBJECT(typeHandle, keepAlive) FC_INNER_RETURN(ReflectClassBaseObject*, GetRuntimeTypeHelper(__me, typeHandle, keepAlive)) -NOINLINE ReflectModuleBaseObject* GetRuntimeModuleHelper(LPVOID __me, Module *pModule, OBJECTREF keepAlive) -{ - FC_INNER_PROLOG_NO_ME_SETUP(); - if (pModule == NULL) - return NULL; - - OBJECTREF refModule = pModule->GetExposedObjectIfExists(); - if (refModule != NULL) - return (ReflectModuleBaseObject*)OBJECTREFToObject(refModule); - - HELPER_METHOD_FRAME_BEGIN_RET_ATTRIB_1(Frame::FRAME_ATTR_EXACT_DEPTH|Frame::FRAME_ATTR_CAPTURE_DEPTH_2, keepAlive); - refModule = pModule->GetExposedObject(); - HELPER_METHOD_FRAME_END(); - - FC_INNER_EPILOG(); - return (ReflectModuleBaseObject*)OBJECTREFToObject(refModule); -} - -NOINLINE AssemblyBaseObject* GetRuntimeAssemblyHelper(LPVOID __me, Assembly *pAssembly, OBJECTREF keepAlive) -{ - FC_INNER_PROLOG_NO_ME_SETUP(); - if (pAssembly == NULL) - return NULL; - - OBJECTREF refAssembly = (pAssembly != NULL) ? pAssembly->GetExposedObjectIfExists() : NULL; - - if(refAssembly != NULL) - return (AssemblyBaseObject*)OBJECTREFToObject(refAssembly); - - HELPER_METHOD_FRAME_BEGIN_RET_ATTRIB_1(Frame::FRAME_ATTR_EXACT_DEPTH|Frame::FRAME_ATTR_CAPTURE_DEPTH_2, keepAlive); - refAssembly = pAssembly->GetExposedObject(); - HELPER_METHOD_FRAME_END(); - - FC_INNER_EPILOG(); - return (AssemblyBaseObject*)OBJECTREFToObject(refAssembly); -} - FCIMPL1(ReflectClassBaseObject*, RuntimeTypeHandle::GetRuntimeType, EnregisteredTypeHandle th) { FCALL_CONTRACT; @@ -298,23 +261,35 @@ FCIMPL1(INT32, RuntimeTypeHandle::GetCorElementType, ReflectClassBaseObject *pTy } FCIMPLEND -FCIMPL1(AssemblyBaseObject*, RuntimeTypeHandle::GetAssembly, ReflectClassBaseObject *pTypeUNSAFE) { - CONTRACTL { - FCALL_CHECK; - } - CONTRACTL_END; +FCIMPL1(AssemblyBaseObject*, RuntimeTypeHandle::GetAssemblyIfExists, ReflectClassBaseObject *pTypeUNSAFE) +{ + FCALL_CONTRACT; REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE); - if (refType == NULL) - FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle")); + return NULL; Assembly* pAssembly = refType->GetType().GetAssembly(); - - FC_RETURN_ASSEMBLY_OBJECT(pAssembly, refType); + OBJECTREF refAssembly = pAssembly->GetExposedObjectIfExists(); + return (AssemblyBaseObject*)OBJECTREFToObject(refAssembly); } FCIMPLEND +extern "C" void QCALLTYPE RuntimeTypeHandle_GetAssemblySlow(QCall::ObjectHandleOnStack type, QCall::ObjectHandleOnStack assembly) +{ + QCALL_CONTRACT; + + BEGIN_QCALL; + GCX_COOP(); + + if (type.Get() == NULL) + COMPlusThrow(kArgumentNullException, W("Arg_InvalidHandle")); + + Assembly* pAssembly = ((REFLECTCLASSBASEREF)type.Get())->GetType().GetAssembly(); + assembly.Set(pAssembly->GetExposedObject()); + END_QCALL; +} + FCIMPL1(FC_BOOL_RET, RuntimeFieldHandle::AcquiresContextFromThis, FieldDesc* pField) { CONTRACTL { @@ -351,25 +326,35 @@ FCIMPL1(Object*, RuntimeFieldHandle::GetLoaderAllocator, FieldDesc* pField) } FCIMPLEND -FCIMPL1(ReflectModuleBaseObject*, RuntimeTypeHandle::GetModule, ReflectClassBaseObject *pTypeUNSAFE) { - CONTRACTL { - FCALL_CHECK; - } - CONTRACTL_END; - - Module *result; +FCIMPL1(ReflectModuleBaseObject*, RuntimeTypeHandle::GetModuleIfExists, ReflectClassBaseObject *pTypeUNSAFE) +{ + FCALL_CONTRACT; REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE); - if (refType == NULL) - FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle")); - - result = refType->GetType().GetModule(); + return NULL; - FC_RETURN_MODULE_OBJECT(result, refType); + Module* pModule = refType->GetType().GetModule(); + OBJECTREF refModule = pModule->GetExposedObjectIfExists(); + return (ReflectModuleBaseObject*)OBJECTREFToObject(refModule); } FCIMPLEND +extern "C" void QCALLTYPE RuntimeTypeHandle_GetModuleSlow(QCall::ObjectHandleOnStack type, QCall::ObjectHandleOnStack module) +{ + QCALL_CONTRACT; + + BEGIN_QCALL; + GCX_COOP(); + + if (type.Get() == NULL) + COMPlusThrow(kArgumentNullException, W("Arg_InvalidHandle")); + + Module* pModule = ((REFLECTCLASSBASEREF)type.Get())->GetType().GetModule(); + module.Set(pModule->GetExposedObject()); + END_QCALL; +} + FCIMPL1(ReflectClassBaseObject *, RuntimeTypeHandle::GetBaseType, ReflectClassBaseObject *pTypeUNSAFE) { CONTRACTL { FCALL_CHECK; @@ -2679,17 +2664,17 @@ FCIMPL2(FieldDesc*, RuntimeFieldHandle::GetStaticFieldForGenericType, FieldDesc } FCIMPLEND -FCIMPL1(ReflectModuleBaseObject*, AssemblyHandle::GetManifestModule, AssemblyBaseObject* pAssemblyUNSAFE) { +FCIMPL1(ReflectModuleBaseObject*, AssemblyHandle::GetManifestModule, AssemblyBaseObject* pAssemblyUNSAFE) +{ FCALL_CONTRACT; ASSEMBLYREF refAssembly = (ASSEMBLYREF)ObjectToOBJECTREF(pAssemblyUNSAFE); - if (refAssembly == NULL) - FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle")); - - Assembly* currentAssembly = refAssembly->GetAssembly(); + return NULL; - FC_RETURN_MODULE_OBJECT(currentAssembly->GetModule(), refAssembly); + Module* pModule = refAssembly->GetAssembly()->GetModule(); + OBJECTREF refModule = pModule->GetExposedObjectIfExists(); + return (ReflectModuleBaseObject*)OBJECTREFToObject(refModule); } FCIMPLEND @@ -2716,6 +2701,20 @@ FCIMPL1(INT32, AssemblyHandle::GetToken, AssemblyBaseObject* pAssemblyUNSAFE) { } FCIMPLEND +extern "C" void QCALLTYPE AssemblyHandle_GetManifestModuleSlow(QCall::ObjectHandleOnStack assembly, QCall::ObjectHandleOnStack module) +{ + QCALL_CONTRACT; + + BEGIN_QCALL; + GCX_COOP(); + + if (assembly.Get() == NULL) + COMPlusThrow(kArgumentNullException, W("Arg_InvalidHandle")); + + Module* pModule = ((ASSEMBLYREF)assembly.Get())->GetAssembly()->GetModule(); + module.Set(pModule->GetExposedObject()); + END_QCALL; +} extern "C" void QCALLTYPE ModuleHandle_GetPEKind(QCall::ModuleHandle pModule, DWORD* pdwPEKind, DWORD* pdwMachine) { diff --git a/src/coreclr/vm/runtimehandles.h b/src/coreclr/vm/runtimehandles.h index ee1977997fecc..fd6661b791ca3 100644 --- a/src/coreclr/vm/runtimehandles.h +++ b/src/coreclr/vm/runtimehandles.h @@ -119,9 +119,9 @@ class RuntimeTypeHandle { static FCDECL2(FC_BOOL_RET, IsEquivalentTo, ReflectClassBaseObject *rtType1UNSAFE, ReflectClassBaseObject *rtType2UNSAFE); - static FCDECL1(AssemblyBaseObject*, GetAssembly, ReflectClassBaseObject *pType); + static FCDECL1(AssemblyBaseObject*, GetAssemblyIfExists, ReflectClassBaseObject *pType); static FCDECL1(ReflectClassBaseObject*, GetBaseType, ReflectClassBaseObject* pType); - static FCDECL1(ReflectModuleBaseObject*, GetModule, ReflectClassBaseObject* pType); + static FCDECL1(ReflectModuleBaseObject*, GetModuleIfExists, ReflectClassBaseObject* pType); static FCDECL1(INT32, GetAttributes, ReflectClassBaseObject* pType); static FCDECL1(INT32, GetToken, ReflectClassBaseObject* pType); static FCDECL1(LPCUTF8, GetUtf8Name, ReflectClassBaseObject* pType); @@ -191,6 +191,8 @@ extern "C" void QCALLTYPE RuntimeTypeHandle_GetInstantiation(QCall::TypeHandle p extern "C" void QCALLTYPE RuntimeTypeHandle_Instantiate(QCall::TypeHandle pTypeHandle, TypeHandle * pInstArray, INT32 cInstArray, QCall::ObjectHandleOnStack retType); extern "C" void QCALLTYPE RuntimeTypeHandle_GetGenericTypeDefinition(QCall::TypeHandle pTypeHandle, QCall::ObjectHandleOnStack retType); extern "C" void QCALLTYPE RuntimeTypeHandle_GetConstraints(QCall::TypeHandle pTypeHandle, QCall::ObjectHandleOnStack retTypes); +extern "C" void QCALLTYPE RuntimeTypeHandle_GetAssemblySlow(QCall::ObjectHandleOnStack type, QCall::ObjectHandleOnStack assembly); +extern "C" void QCALLTYPE RuntimeTypeHandle_GetModuleSlow(QCall::ObjectHandleOnStack type, QCall::ObjectHandleOnStack module); extern "C" INT32 QCALLTYPE RuntimeTypeHandle_GetNumVirtualsAndStaticVirtuals(QCall::TypeHandle pTypeHandle); extern "C" void QCALLTYPE RuntimeTypeHandle_VerifyInterfaceIsImplemented(QCall::TypeHandle pTypeHandle, QCall::TypeHandle pIFaceHandle); extern "C" MethodDesc* QCALLTYPE RuntimeTypeHandle_GetInterfaceMethodImplementation(QCall::TypeHandle pTypeHandle, QCall::TypeHandle pOwner, MethodDesc * pMD); @@ -330,14 +332,15 @@ extern "C" void QCALLTYPE ModuleHandle_GetAssembly(QCall::ModuleHandle pModule, extern "C" void QCALLTYPE ModuleHandle_GetPEKind(QCall::ModuleHandle pModule, DWORD* pdwPEKind, DWORD* pdwMachine); -class AssemblyHandle { - +class AssemblyHandle +{ public: static FCDECL1(ReflectModuleBaseObject*, GetManifestModule, AssemblyBaseObject *pAssemblyUNSAFE); - static FCDECL1(INT32, GetToken, AssemblyBaseObject *pAssemblyUNSAFE); }; +extern "C" void QCALLTYPE AssemblyHandle_GetManifestModuleSlow(QCall::ObjectHandleOnStack assembly, QCall::ObjectHandleOnStack module); + class SignatureNative; typedef DPTR(SignatureNative) PTR_SignatureNative; diff --git a/src/coreclr/vm/threads.cpp b/src/coreclr/vm/threads.cpp index f9fbfec9bc661..99a366e9a2f13 100644 --- a/src/coreclr/vm/threads.cpp +++ b/src/coreclr/vm/threads.cpp @@ -3116,14 +3116,14 @@ DWORD MsgWaitHelper(int numWaiters, HANDLE* phEvent, BOOL bWaitAll, DWORD millis // want true WAIT_ALL, we need to fire up a different thread in the MTA and wait // on its result. This isn't implemented yet. // - // A change was added to WaitHandleNative::CorWaitMultipleNative to disable WaitAll + // A change was added to WaitHandle_WaitMultipleIgnoringSyncContext to disable WaitAll // in an STA with more than one handle. if (bWaitAll) { if (numWaiters == 1) bWaitAll = FALSE; - // The check that's supposed to prevent this condition from occurring, in WaitHandleNative::CorWaitMultipleNative, + // The check that's supposed to prevent this condition from occurring, in WaitHandle_WaitMultipleIgnoringSyncContext, // is unfortunately behind FEATURE_COMINTEROP instead of FEATURE_COMINTEROP_APARTMENT_SUPPORT. // So on CoreCLR (where FEATURE_COMINTEROP is not currently defined) we can actually reach this point. // We can't fix this, because it's a breaking change, so we just won't assert here. diff --git a/src/coreclr/vm/threads.h b/src/coreclr/vm/threads.h index f3b7894c3dea6..44a537e7fe905 100644 --- a/src/coreclr/vm/threads.h +++ b/src/coreclr/vm/threads.h @@ -468,7 +468,6 @@ class Thread friend class ThreadSuspend; friend class SyncBlock; friend struct PendingSync; - friend class ThreadNative; #ifdef _DEBUG friend class EEContract; #endif @@ -2706,6 +2705,24 @@ class Thread #endif // TRACK_SYNC + // Access to thread handle and ThreadId. + HANDLE GetThreadHandle() + { + LIMITED_METHOD_CONTRACT; +#if defined(_DEBUG) && !defined(DACCESS_COMPILE) + { + CounterHolder handleHolder(&m_dwThreadHandleBeingUsed); + HANDLE handle = m_ThreadHandle; + _ASSERTE ( handle == INVALID_HANDLE_VALUE + || m_OSThreadId == 0 + || m_OSThreadId == 0xbaadf00d + || ::MatchThreadHandleToOsId(handle, (DWORD)m_OSThreadId) ); + } +#endif + DACCOP_IGNORE(FieldAccess, "Treated as raw address, no marshaling is necessary"); + return m_ThreadHandle; + } + private: // For suspends: CLREvent m_DebugSuspendEvent; @@ -2729,25 +2746,6 @@ class Thread return walk; } - // Access to thread handle and ThreadId. - HANDLE GetThreadHandle() - { - LIMITED_METHOD_CONTRACT; -#if defined(_DEBUG) && !defined(DACCESS_COMPILE) - { - CounterHolder handleHolder(&m_dwThreadHandleBeingUsed); - HANDLE handle = m_ThreadHandle; - _ASSERTE ( handle == INVALID_HANDLE_VALUE - || m_OSThreadId == 0 - || m_OSThreadId == 0xbaadf00d - || ::MatchThreadHandleToOsId(handle, (DWORD)m_OSThreadId) ); - } -#endif - - DACCOP_IGNORE(FieldAccess, "Treated as raw address, no marshaling is necessary"); - return m_ThreadHandle; - } - void SetThreadHandle(HANDLE h) { LIMITED_METHOD_CONTRACT; diff --git a/src/coreclr/vm/threadstatics.cpp b/src/coreclr/vm/threadstatics.cpp index 14252ca2ae06c..dbb218464a61e 100644 --- a/src/coreclr/vm/threadstatics.cpp +++ b/src/coreclr/vm/threadstatics.cpp @@ -33,7 +33,6 @@ static TLSIndexToMethodTableMap *g_pThreadStaticCollectibleTypeIndices; static TLSIndexToMethodTableMap *g_pThreadStaticNonCollectibleTypeIndices; static PTR_MethodTable g_pMethodTablesForDirectThreadLocalData[offsetof(ThreadLocalData, ExtendedDirectThreadLocalTLSData) - offsetof(ThreadLocalData, ThreadBlockingInfo_First) + EXTENDED_DIRECT_THREAD_LOCAL_SIZE]; -static Volatile s_GCsWhichDoRelocateAndCanEmptyOutTheTLSIndices = 0; static uint32_t g_NextTLSSlot = 1; static uint32_t g_NextNonCollectibleTlsSlot = NUMBER_OF_TLSOFFSETS_NOT_USED_IN_NONCOLLECTIBLE_ARRAY; static uint32_t g_directThreadLocalTLSBytesAvailable = EXTENDED_DIRECT_THREAD_LOCAL_SIZE; @@ -277,7 +276,7 @@ void TLSIndexToMethodTableMap::Clear(TLSIndex index, uint8_t whenCleared) _ASSERTE(IsClearedValue(pMap[index.GetIndexOffset()])); } -bool TLSIndexToMethodTableMap::FindClearedIndex(uint8_t whenClearedMarkerToAvoid, TLSIndex* pIndex) +bool TLSIndexToMethodTableMap::FindClearedIndex(TLSIndex* pIndex) { CONTRACTL { @@ -291,15 +290,6 @@ bool TLSIndexToMethodTableMap::FindClearedIndex(uint8_t whenClearedMarkerToAvoid { if (entry.IsClearedValue) { - uint8_t whenClearedMarker = entry.ClearedMarker; - if ((whenClearedMarker == whenClearedMarkerToAvoid) || - (whenClearedMarker == (whenClearedMarkerToAvoid - 1)) || - (whenClearedMarker == (whenClearedMarkerToAvoid - 2))) - { - // Make sure we are not within 2 of the marker we are trying to avoid - // Use multiple compares instead of trying to fuss around with the overflow style comparisons - continue; - } *pIndex = entry.TlsIndex; return true; } @@ -317,7 +307,7 @@ void InitializeThreadStaticData() } CONTRACTL_END; - g_pThreadStaticCollectibleTypeIndices = new TLSIndexToMethodTableMap(TLSIndexType::NonCollectible); + g_pThreadStaticCollectibleTypeIndices = new TLSIndexToMethodTableMap(TLSIndexType::Collectible); g_pThreadStaticNonCollectibleTypeIndices = new TLSIndexToMethodTableMap(TLSIndexType::NonCollectible); g_TLSCrst.Init(CrstThreadLocalStorageLock, CRST_UNSAFE_ANYMODE); } @@ -387,7 +377,7 @@ void FreeLoaderAllocatorHandlesForTLSData(Thread *pThread) #endif for (const auto& entry : g_pThreadStaticCollectibleTypeIndices->CollectibleEntries()) { - _ASSERTE((entry.TlsIndex.GetIndexOffset() < pThread->cLoaderHandles) || allRemainingIndicesAreNotValid); + _ASSERTE((entry.TlsIndex.GetIndexOffset() <= pThread->cLoaderHandles) || allRemainingIndicesAreNotValid); if (entry.TlsIndex.GetIndexOffset() >= pThread->cLoaderHandles) { #ifndef _DEBUG @@ -405,6 +395,13 @@ void FreeLoaderAllocatorHandlesForTLSData(Thread *pThread) } } } + + pThread->cLoaderHandles = -1; // Sentinel value indicating that there are no LoaderHandles and the thread is permanently dead. + if (pThread->pLoaderHandles != NULL) + { + delete[] pThread->pLoaderHandles; + pThread->pLoaderHandles = NULL; + } } } @@ -431,34 +428,46 @@ void FreeThreadStaticData(Thread* pThread) } CONTRACTL_END; - SpinLockHolder spinLock(&pThread->m_TlsSpinLock); + InFlightTLSData* pOldInFlightData = nullptr; - ThreadLocalData *pThreadLocalData = &t_ThreadStatics; + int32_t oldCollectibleTlsDataCount = 0; + DPTR(OBJECTHANDLE) pOldCollectibleTlsArrayData = nullptr; - for (int32_t iTlsSlot = 0; iTlsSlot < pThreadLocalData->cCollectibleTlsData; ++iTlsSlot) { - if (!IsHandleNullUnchecked(pThreadLocalData->pCollectibleTlsArrayData[iTlsSlot])) + SpinLockHolder spinLock(&pThread->m_TlsSpinLock); + + ThreadLocalData *pThreadLocalData = &t_ThreadStatics; + + pOldCollectibleTlsArrayData = pThreadLocalData->pCollectibleTlsArrayData; + oldCollectibleTlsDataCount = pThreadLocalData->cCollectibleTlsData; + + pThreadLocalData->pCollectibleTlsArrayData = NULL; + pThreadLocalData->cCollectibleTlsData = 0; + pThreadLocalData->pNonCollectibleTlsArrayData = NULL; + pThreadLocalData->cNonCollectibleTlsData = 0; + + pOldInFlightData = pThreadLocalData->pInFlightData; + pThreadLocalData->pInFlightData = NULL; + _ASSERTE(pThreadLocalData->pThread == pThread); + pThreadLocalData->pThread = NULL; + } + + for (int32_t iTlsSlot = 0; iTlsSlot < oldCollectibleTlsDataCount; ++iTlsSlot) + { + if (!IsHandleNullUnchecked(pOldCollectibleTlsArrayData[iTlsSlot])) { - DestroyLongWeakHandle(pThreadLocalData->pCollectibleTlsArrayData[iTlsSlot]); + DestroyLongWeakHandle(pOldCollectibleTlsArrayData[iTlsSlot]); } } - delete[] (uint8_t*)pThreadLocalData->pCollectibleTlsArrayData; - - pThreadLocalData->pCollectibleTlsArrayData = 0; - pThreadLocalData->cCollectibleTlsData = 0; - pThreadLocalData->pNonCollectibleTlsArrayData = 0; - pThreadLocalData->cNonCollectibleTlsData = 0; + delete[] (uint8_t*)pOldCollectibleTlsArrayData; - while (pThreadLocalData->pInFlightData != NULL) + while (pOldInFlightData != NULL) { - InFlightTLSData* pInFlightData = pThreadLocalData->pInFlightData; - pThreadLocalData->pInFlightData = pInFlightData->pNext; + InFlightTLSData* pInFlightData = pOldInFlightData; + pOldInFlightData = pInFlightData->pNext; delete pInFlightData; } - - _ASSERTE(pThreadLocalData->pThread == pThread); - pThreadLocalData->pThread = NULL; } void SetTLSBaseValue(TADDR *ppTLSBaseAddress, TADDR pTLSBaseAddress, bool useGCBarrierInsteadOfHandleStore) @@ -553,6 +562,8 @@ void* GetThreadLocalStaticBase(TLSIndex index) delete[] pOldArray; } + _ASSERTE(t_ThreadStatics.pThread->cLoaderHandles != -1); // Check sentinel value indicating that there are no LoaderHandles, the thread has gone through termination and is permanently dead. + if (isCollectible && t_ThreadStatics.pThread->cLoaderHandles <= index.GetIndexOffset()) { // Grow the underlying TLS array @@ -594,9 +605,11 @@ void* GetThreadLocalStaticBase(TLSIndex index) gcBaseAddresses.pTLSBaseAddress = dac_cast(OBJECTREFToObject(ObjectFromHandle(pInFlightData->hTLSData))); if (pMT->IsClassInited()) { - SpinLockHolder spinLock(&t_ThreadStatics.pThread->m_TlsSpinLock); - SetTLSBaseValue(gcBaseAddresses.ppTLSBaseAddress, gcBaseAddresses.pTLSBaseAddress, staticIsNonCollectible); - *ppOldNextPtr = pInFlightData->pNext; + { + SpinLockHolder spinLock(&t_ThreadStatics.pThread->m_TlsSpinLock); + SetTLSBaseValue(gcBaseAddresses.ppTLSBaseAddress, gcBaseAddresses.pTLSBaseAddress, staticIsNonCollectible); + *ppOldNextPtr = pInFlightData->pNext; + } delete pInFlightData; } break; @@ -744,7 +757,7 @@ void GetTLSIndexForThreadStatic(MethodTable* pMT, bool gcStatic, TLSIndex* pInde } else { - if (!g_pThreadStaticCollectibleTypeIndices->FindClearedIndex(s_GCsWhichDoRelocateAndCanEmptyOutTheTLSIndices, &newTLSIndex)) + if (!g_pThreadStaticCollectibleTypeIndices->FindClearedIndex(&newTLSIndex)) { uint32_t tlsRawIndex = g_NextTLSSlot; newTLSIndex = TLSIndex(TLSIndexType::Collectible, tlsRawIndex); @@ -777,7 +790,7 @@ void FreeTLSIndicesForLoaderAllocator(LoaderAllocator *pLoaderAllocator) while (current != end) { - g_pThreadStaticCollectibleTypeIndices->Clear(tlsIndicesToCleanup[current], s_GCsWhichDoRelocateAndCanEmptyOutTheTLSIndices); + g_pThreadStaticCollectibleTypeIndices->Clear(tlsIndicesToCleanup[current], 0); ++current; } } diff --git a/src/coreclr/vm/threadstatics.h b/src/coreclr/vm/threadstatics.h index 3ab3806cbf952..4d979d168bf01 100644 --- a/src/coreclr/vm/threadstatics.h +++ b/src/coreclr/vm/threadstatics.h @@ -304,7 +304,7 @@ class TLSIndexToMethodTableMap #ifndef DACCESS_COMPILE void Set(TLSIndex index, PTR_MethodTable pMT, bool isGCStatic); - bool FindClearedIndex(uint8_t whenClearedMarkerToAvoid, TLSIndex* pIndex); + bool FindClearedIndex(TLSIndex* pIndex); void Clear(TLSIndex index, uint8_t whenCleared); #endif // !DACCESS_COMPILE diff --git a/src/installer/tests/HostActivation.Tests/FrameworkResolution/ApplyPatchesSettings.cs b/src/installer/tests/HostActivation.Tests/FrameworkResolution/ApplyPatchesSettings.cs index d747ee016f47d..3d00d7a02db58 100644 --- a/src/installer/tests/HostActivation.Tests/FrameworkResolution/ApplyPatchesSettings.cs +++ b/src/installer/tests/HostActivation.Tests/FrameworkResolution/ApplyPatchesSettings.cs @@ -5,6 +5,8 @@ using Microsoft.DotNet.Cli.Build.Framework; using Xunit; +using static Microsoft.DotNet.CoreSetup.Test.Constants; + namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.FrameworkResolution { public class ApplyPatchesSettings : diff --git a/src/installer/tests/HostActivation.Tests/FrameworkResolution/ComplexHierarchies.cs b/src/installer/tests/HostActivation.Tests/FrameworkResolution/ComplexHierarchies.cs index 9a474ba7de7c0..b8c3f82e77485 100644 --- a/src/installer/tests/HostActivation.Tests/FrameworkResolution/ComplexHierarchies.cs +++ b/src/installer/tests/HostActivation.Tests/FrameworkResolution/ComplexHierarchies.cs @@ -6,6 +6,8 @@ using System; using Xunit; +using static Microsoft.DotNet.CoreSetup.Test.Constants; + namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.FrameworkResolution { public class ComplexHierarchies : diff --git a/src/installer/tests/HostActivation.Tests/FrameworkResolution/FrameworkResolutionBase.Settings.cs b/src/installer/tests/HostActivation.Tests/FrameworkResolution/FrameworkResolutionBase.Settings.cs index 81f2e14a35f52..9b8a63b9a6502 100644 --- a/src/installer/tests/HostActivation.Tests/FrameworkResolution/FrameworkResolutionBase.Settings.cs +++ b/src/installer/tests/HostActivation.Tests/FrameworkResolution/FrameworkResolutionBase.Settings.cs @@ -85,7 +85,7 @@ public enum SettingLocation public static Func RollForwardSetting( SettingLocation location, string value, - string frameworkReferenceName = MicrosoftNETCoreApp) + string frameworkReferenceName = Constants.MicrosoftNETCoreApp) { if (value == null || location == SettingLocation.None) { @@ -114,7 +114,7 @@ public static Func RollForwardSetting( public static Func RollForwardOnNoCandidateFxSetting( SettingLocation location, int? value, - string frameworkReferenceName = MicrosoftNETCoreApp) + string frameworkReferenceName = Constants.MicrosoftNETCoreApp) { if (!value.HasValue || location == SettingLocation.None) { @@ -143,7 +143,7 @@ public static Func RollForwardOnNoCandidateFxSetting public static Func ApplyPatchesSetting( SettingLocation location, bool? value, - string frameworkReferenceName = MicrosoftNETCoreApp) + string frameworkReferenceName = Constants.MicrosoftNETCoreApp) { if (!value.HasValue || location == SettingLocation.None) { diff --git a/src/installer/tests/HostActivation.Tests/FrameworkResolution/FrameworkResolutionBase.cs b/src/installer/tests/HostActivation.Tests/FrameworkResolution/FrameworkResolutionBase.cs index a0ce8d0cf3963..b098994df8ae6 100644 --- a/src/installer/tests/HostActivation.Tests/FrameworkResolution/FrameworkResolutionBase.cs +++ b/src/installer/tests/HostActivation.Tests/FrameworkResolution/FrameworkResolutionBase.cs @@ -11,8 +11,6 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.FrameworkResolution { public abstract partial class FrameworkResolutionBase { - protected const string MicrosoftNETCoreApp = "Microsoft.NETCore.App"; - public static class ResolvedFramework { public const string NotFound = "[not found]"; @@ -23,7 +21,6 @@ protected CommandResult RunTest( DotNetCli dotnet, TestApp app, TestSettings settings, - Action resultAction = null, bool? multiLevelLookup = false) { using (DotNetCliExtensions.DotNetCliCustomizer dotnetCustomizer = settings.DotnetCustomizer == null ? null : dotnet.Customize()) @@ -53,8 +50,6 @@ protected CommandResult RunTest( .Environment(settings.Environment) .Execute(); - resultAction?.Invoke(result); - return result; } } diff --git a/src/installer/tests/HostActivation.Tests/FrameworkResolution/FxVersionCLI.cs b/src/installer/tests/HostActivation.Tests/FrameworkResolution/FxVersionCLI.cs index 10057216bc36d..5d09a35ff67b8 100644 --- a/src/installer/tests/HostActivation.Tests/FrameworkResolution/FxVersionCLI.cs +++ b/src/installer/tests/HostActivation.Tests/FrameworkResolution/FxVersionCLI.cs @@ -5,6 +5,8 @@ using Microsoft.DotNet.Cli.Build.Framework; using Xunit; +using static Microsoft.DotNet.CoreSetup.Test.Constants; + namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.FrameworkResolution { public class FXVersionCLI : diff --git a/src/installer/tests/HostActivation.Tests/FrameworkResolution/IncludedFrameworksSettings.cs b/src/installer/tests/HostActivation.Tests/FrameworkResolution/IncludedFrameworksSettings.cs index af8aa1dc3b593..ec5ae8306693c 100644 --- a/src/installer/tests/HostActivation.Tests/FrameworkResolution/IncludedFrameworksSettings.cs +++ b/src/installer/tests/HostActivation.Tests/FrameworkResolution/IncludedFrameworksSettings.cs @@ -5,6 +5,8 @@ using Microsoft.DotNet.Cli.Build.Framework; using Xunit; +using static Microsoft.DotNet.CoreSetup.Test.Constants; + namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.FrameworkResolution { public class IncludedFrameworksSettings : diff --git a/src/installer/tests/HostActivation.Tests/FrameworkResolution/MultipleHives.cs b/src/installer/tests/HostActivation.Tests/FrameworkResolution/MultipleHives.cs index 1fb612efb3826..e44a58272515f 100644 --- a/src/installer/tests/HostActivation.Tests/FrameworkResolution/MultipleHives.cs +++ b/src/installer/tests/HostActivation.Tests/FrameworkResolution/MultipleHives.cs @@ -8,6 +8,7 @@ using Microsoft.DotNet.Cli.Build; using Microsoft.DotNet.Cli.Build.Framework; using Xunit; +using static Microsoft.DotNet.CoreSetup.Test.Constants; namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.FrameworkResolution { @@ -217,6 +218,50 @@ public void FrameworkResolutionError(string tfm, bool? multiLevelLookup, bool ef .And.HaveStdErrContaining("Ignoring FX version [9999.9.9] without .deps.json"); } + [Fact] + public void FrameworkResolutionError_ListOtherArchitectures() + { + using (var registeredInstallLocationOverride = new RegisteredInstallLocationOverride(SharedState.DotNetMainHive.GreatestVersionHostFxrFilePath)) + using (var otherArchArtifact = TestArtifact.Create("otherArch")) + { + string requestedVersion = "9999.9.9"; + string[] otherArchs = ["arm64", "x64", "x86"]; + var installLocations = new (string, string)[otherArchs.Length]; + for (int i = 0; i < otherArchs.Length; i++) + { + string arch = otherArchs[i]; + + // Create a .NET install with Microsoft.NETCoreApp at the registered location + var dotnet = new DotNetBuilder(otherArchArtifact.Location, TestContext.BuiltDotNet.BinPath, arch) + .AddMicrosoftNETCoreAppFrameworkMockHostPolicy(requestedVersion) + .Build(); + installLocations[i] = (arch, dotnet.BinPath); + } + + registeredInstallLocationOverride.SetInstallLocation(installLocations); + + CommandResult result = RunTest( + new TestSettings() + .WithRuntimeConfigCustomizer(c => c.WithFramework(MicrosoftNETCoreApp, requestedVersion)) + .WithEnvironment(TestOnlyEnvironmentVariables.RegisteredConfigLocation, registeredInstallLocationOverride.PathValueOverride), + multiLevelLookup: null); + + result.ShouldFailToFindCompatibleFrameworkVersion(MicrosoftNETCoreApp, requestedVersion) + .And.HaveStdErrContaining("The following frameworks for other architectures were found:"); + + // Error message should list framework found for other architectures + foreach ((string arch, string path) in installLocations) + { + if (arch == TestContext.BuildArchitecture) + continue; + + string expectedPath = System.Text.RegularExpressions.Regex.Escape(Path.Combine(path, "shared", MicrosoftNETCoreApp)); + result.Should() + .HaveStdErrMatching($@"{arch}\s*{requestedVersion} at \[{expectedPath}\]", System.Text.RegularExpressions.RegexOptions.Multiline); + } + } + } + private CommandResult RunTest(Func runtimeConfig, bool? multiLevelLookup = true) => RunTest(new TestSettings().WithRuntimeConfigCustomizer(runtimeConfig), multiLevelLookup); diff --git a/src/installer/tests/HostActivation.Tests/FrameworkResolution/RollForwardAndRollForwardOnNoCandidateFxSettings.cs b/src/installer/tests/HostActivation.Tests/FrameworkResolution/RollForwardAndRollForwardOnNoCandidateFxSettings.cs index 6555683bacd12..ab486868f661e 100644 --- a/src/installer/tests/HostActivation.Tests/FrameworkResolution/RollForwardAndRollForwardOnNoCandidateFxSettings.cs +++ b/src/installer/tests/HostActivation.Tests/FrameworkResolution/RollForwardAndRollForwardOnNoCandidateFxSettings.cs @@ -5,6 +5,8 @@ using Microsoft.DotNet.Cli.Build.Framework; using Xunit; +using static Microsoft.DotNet.CoreSetup.Test.Constants; + namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.FrameworkResolution { public class RollForwardAndRollForwardOnNoCandidateFxSettings : diff --git a/src/installer/tests/HostActivation.Tests/FrameworkResolution/RollForwardMultipleFrameworks.cs b/src/installer/tests/HostActivation.Tests/FrameworkResolution/RollForwardMultipleFrameworks.cs index 26e2d11a2f13a..8501e85e3698a 100644 --- a/src/installer/tests/HostActivation.Tests/FrameworkResolution/RollForwardMultipleFrameworks.cs +++ b/src/installer/tests/HostActivation.Tests/FrameworkResolution/RollForwardMultipleFrameworks.cs @@ -6,6 +6,8 @@ using System; using Xunit; +using static Microsoft.DotNet.CoreSetup.Test.Constants; + namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.FrameworkResolution { public class RollForwardMultipleFrameworks : diff --git a/src/installer/tests/HostActivation.Tests/FrameworkResolution/RollForwardOnNoCandidateFx.cs b/src/installer/tests/HostActivation.Tests/FrameworkResolution/RollForwardOnNoCandidateFx.cs index 20a3f7796de86..835976248aed9 100644 --- a/src/installer/tests/HostActivation.Tests/FrameworkResolution/RollForwardOnNoCandidateFx.cs +++ b/src/installer/tests/HostActivation.Tests/FrameworkResolution/RollForwardOnNoCandidateFx.cs @@ -1,11 +1,13 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; using Microsoft.DotNet.Cli.Build; using Microsoft.DotNet.Cli.Build.Framework; -using System; using Xunit; +using static Microsoft.DotNet.CoreSetup.Test.Constants; + namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.FrameworkResolution { public class RollForwardOnNoCandidateFx : diff --git a/src/installer/tests/HostActivation.Tests/FrameworkResolution/RollForwardOnNoCandidateFxMultipleFrameworks.cs b/src/installer/tests/HostActivation.Tests/FrameworkResolution/RollForwardOnNoCandidateFxMultipleFrameworks.cs index 8db6771f6c042..ff756cb7c774f 100644 --- a/src/installer/tests/HostActivation.Tests/FrameworkResolution/RollForwardOnNoCandidateFxMultipleFrameworks.cs +++ b/src/installer/tests/HostActivation.Tests/FrameworkResolution/RollForwardOnNoCandidateFxMultipleFrameworks.cs @@ -6,6 +6,8 @@ using System; using Xunit; +using static Microsoft.DotNet.CoreSetup.Test.Constants; + namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.FrameworkResolution { public class RollForwardOnNoCandidateFxMultipleFrameworks : diff --git a/src/installer/tests/HostActivation.Tests/FrameworkResolution/RollForwardOnNoCandidateFxSettings.cs b/src/installer/tests/HostActivation.Tests/FrameworkResolution/RollForwardOnNoCandidateFxSettings.cs index b18b8c8131c6b..1e32c44da644b 100644 --- a/src/installer/tests/HostActivation.Tests/FrameworkResolution/RollForwardOnNoCandidateFxSettings.cs +++ b/src/installer/tests/HostActivation.Tests/FrameworkResolution/RollForwardOnNoCandidateFxSettings.cs @@ -5,6 +5,8 @@ using Microsoft.DotNet.Cli.Build.Framework; using Xunit; +using static Microsoft.DotNet.CoreSetup.Test.Constants; + namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.FrameworkResolution { public class RollForwardOnNoCandidateFxSettings : diff --git a/src/installer/tests/HostActivation.Tests/FrameworkResolution/RollForwardPreReleaseOnly.cs b/src/installer/tests/HostActivation.Tests/FrameworkResolution/RollForwardPreReleaseOnly.cs index 9e35ed8ff2a63..332a1b6e2a978 100644 --- a/src/installer/tests/HostActivation.Tests/FrameworkResolution/RollForwardPreReleaseOnly.cs +++ b/src/installer/tests/HostActivation.Tests/FrameworkResolution/RollForwardPreReleaseOnly.cs @@ -5,6 +5,8 @@ using Microsoft.DotNet.Cli.Build.Framework; using Xunit; +using static Microsoft.DotNet.CoreSetup.Test.Constants; + namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.FrameworkResolution { /// diff --git a/src/installer/tests/HostActivation.Tests/FrameworkResolution/RollForwardReleaseAndPreRelease.cs b/src/installer/tests/HostActivation.Tests/FrameworkResolution/RollForwardReleaseAndPreRelease.cs index 5305d1abbc60b..88d6f0c459d0a 100644 --- a/src/installer/tests/HostActivation.Tests/FrameworkResolution/RollForwardReleaseAndPreRelease.cs +++ b/src/installer/tests/HostActivation.Tests/FrameworkResolution/RollForwardReleaseAndPreRelease.cs @@ -5,6 +5,8 @@ using Microsoft.DotNet.Cli.Build.Framework; using Xunit; +using static Microsoft.DotNet.CoreSetup.Test.Constants; + namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.FrameworkResolution { /// diff --git a/src/installer/tests/HostActivation.Tests/FrameworkResolution/RollForwardReleaseOnly.cs b/src/installer/tests/HostActivation.Tests/FrameworkResolution/RollForwardReleaseOnly.cs index cd92cabd1b772..48e2f551a473d 100644 --- a/src/installer/tests/HostActivation.Tests/FrameworkResolution/RollForwardReleaseOnly.cs +++ b/src/installer/tests/HostActivation.Tests/FrameworkResolution/RollForwardReleaseOnly.cs @@ -5,6 +5,8 @@ using Microsoft.DotNet.Cli.Build.Framework; using Xunit; +using static Microsoft.DotNet.CoreSetup.Test.Constants; + namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.FrameworkResolution { /// diff --git a/src/installer/tests/HostActivation.Tests/FrameworkResolution/RollForwardSettings.cs b/src/installer/tests/HostActivation.Tests/FrameworkResolution/RollForwardSettings.cs index b5e278c74ccab..2f5d836c63971 100644 --- a/src/installer/tests/HostActivation.Tests/FrameworkResolution/RollForwardSettings.cs +++ b/src/installer/tests/HostActivation.Tests/FrameworkResolution/RollForwardSettings.cs @@ -5,6 +5,8 @@ using Microsoft.DotNet.Cli.Build.Framework; using Xunit; +using static Microsoft.DotNet.CoreSetup.Test.Constants; + namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.FrameworkResolution { public class RollForwardSettings : diff --git a/src/installer/tests/TestUtils/Constants.cs b/src/installer/tests/TestUtils/Constants.cs index 4ae6587dd6407..9eb5b6e661e32 100644 --- a/src/installer/tests/TestUtils/Constants.cs +++ b/src/installer/tests/TestUtils/Constants.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; + namespace Microsoft.DotNet.CoreSetup.Test { public static class Constants @@ -82,8 +84,10 @@ public static class DisableGuiErrors public static class TestOnlyEnvironmentVariables { public const string DefaultInstallPath = "_DOTNET_TEST_DEFAULT_INSTALL_PATH"; - public const string RegistryPath = "_DOTNET_TEST_REGISTRY_PATH"; public const string GloballyRegisteredPath = "_DOTNET_TEST_GLOBALLY_REGISTERED_PATH"; + + public static string RegisteredConfigLocation = OperatingSystem.IsWindows() ? RegistryPath : InstallLocationPath; + public const string RegistryPath = "_DOTNET_TEST_REGISTRY_PATH"; public const string InstallLocationPath = "_DOTNET_TEST_INSTALL_LOCATION_PATH"; } diff --git a/src/libraries/Common/tests/WasmTestRunner/WasmTestRunner.cs b/src/libraries/Common/tests/WasmTestRunner/WasmTestRunner.cs index 1cf1b35cf291a..8c393b95f69c2 100644 --- a/src/libraries/Common/tests/WasmTestRunner/WasmTestRunner.cs +++ b/src/libraries/Common/tests/WasmTestRunner/WasmTestRunner.cs @@ -20,7 +20,7 @@ public static int Main(string[] args) return PollWasiEventLoopUntilResolved((Thread)null!, MainAsync(args)); [UnsafeAccessor(UnsafeAccessorKind.StaticMethod, Name = "PollWasiEventLoopUntilResolved")] - static extern int PollWasiEventLoopUntilResolved(Thread t, Task mainTask); + static extern T PollWasiEventLoopUntilResolved(Thread t, Task mainTask); } diff --git a/src/libraries/System.Numerics.Tensors/tests/TensorSpanTests.cs b/src/libraries/System.Numerics.Tensors/tests/TensorSpanTests.cs index f03f682f94f70..737ba5cf5374b 100644 --- a/src/libraries/System.Numerics.Tensors/tests/TensorSpanTests.cs +++ b/src/libraries/System.Numerics.Tensors/tests/TensorSpanTests.cs @@ -486,12 +486,13 @@ public void TensorExtensionsTwoSpanInSpanOut(TensorPrimitivesTwoSpanInSpanOut public static IEnumerable TwoSpanInFloatOutData() { yield return Create(TensorPrimitives.Distance, Tensor.Distance); - //yield return Create(TensorPrimitives.Dot, Tensor.Dot); + yield return Create(TensorPrimitives.Dot, Tensor.Dot); static object[] Create(TensorPrimitivesTwoSpanInTOut tensorPrimitivesMethod, TensorTwoSpanInTOut tensorOperation) => new object[] { tensorPrimitivesMethod, tensorOperation }; } + [ActiveIssue("https://github.com/dotnet/runtime/issues/107254")] [Theory, MemberData(nameof(TwoSpanInFloatOutData))] public void TensorExtensionsTwoSpanInFloatOut(TensorPrimitivesTwoSpanInTOut tensorPrimitivesOperation, TensorTwoSpanInTOut tensorOperation) where T : INumberBase diff --git a/src/libraries/System.Numerics.Vectors/tests/GenericVectorTests.cs b/src/libraries/System.Numerics.Vectors/tests/GenericVectorTests.cs index 822bb136dffbc..28ed4f701d469 100644 --- a/src/libraries/System.Numerics.Vectors/tests/GenericVectorTests.cs +++ b/src/libraries/System.Numerics.Vectors/tests/GenericVectorTests.cs @@ -52,7 +52,6 @@ static GenericVectorTests() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/81785", TestPlatforms.Browser)] public unsafe void IsHardwareAcceleratedTest() { MethodInfo methodInfo = typeof(Vector).GetMethod("get_IsHardwareAccelerated"); @@ -1094,10 +1093,8 @@ private void TestToString(string format, IFormatProvider provider) where T : [Fact] public void AdditionInt64() { TestAddition(); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void AdditionSingle() { TestAddition(); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void AdditionDouble() { TestAddition(); } private void TestAddition() where T : struct, INumber { @@ -1161,10 +1158,8 @@ private void TestAdditionOverflow() where T : struct, INumber [Fact] public void SubtractionInt64() { TestSubtraction(); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void SubtractionSingle() { TestSubtraction(); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void SubtractionDouble() { TestSubtraction(); } private void TestSubtraction() where T : struct, INumber { @@ -1228,10 +1223,8 @@ private void TestSubtractionOverflow() where T : struct, INumber [Fact] public void MultiplicationInt64() { TestMultiplication(); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void MultiplicationSingle() { TestMultiplication(); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void MultiplicationDouble() { TestMultiplication(); } private void TestMultiplication() where T : struct, INumber { @@ -1272,11 +1265,9 @@ private void TestMultiplication() where T : struct, INumber [ActiveIssue("https://github.com/dotnet/runtime/issues/67893", TestPlatforms.tvOS)] public void MultiplicationWithScalarInt64() { TestMultiplicationWithScalar(); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] [ActiveIssue("https://github.com/dotnet/runtime/issues/67893", TestPlatforms.tvOS)] public void MultiplicationWithScalarSingle() { TestMultiplicationWithScalar(); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] [ActiveIssue("https://github.com/dotnet/runtime/issues/67893", TestPlatforms.tvOS)] public void MultiplicationWithScalarDouble() { TestMultiplicationWithScalar(); } private void TestMultiplicationWithScalar() where T : struct, INumber @@ -1318,10 +1309,8 @@ private void TestMultiplicationWithScalar() where T : struct, INumber [Fact] public void DivisionInt64() { TestDivision(); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void DivisionSingle() { TestDivision(); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void DivisionDouble() { TestDivision(); } private void TestDivision() where T : struct, INumber { @@ -1388,11 +1377,9 @@ private void TestDivisionByZeroException() where T : struct public void DivisionWithScalarInt64() { TestDivisionWithScalar(); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void DivisionWithScalarSingle() { TestDivisionWithScalar(); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void DivisionWithScalarDouble() { TestDivisionWithScalar(); } private void TestDivisionWithScalar() where T : struct, INumber @@ -1460,10 +1447,8 @@ private void TestDivisionWithScalarByZeroException() where T : struct, INumbe [Fact] public void UnaryMinusInt64() { TestUnaryMinus(); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void UnaryMinusSingle() { TestUnaryMinus(); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void UnaryMinusDouble() { TestUnaryMinus(); } private void TestUnaryMinus() where T : struct, INumber { @@ -1850,10 +1835,8 @@ private void TestShiftRightLogical() where T : unmanaged, IBinaryInteger [Fact] public void VectorGreaterThanInt64() { TestVectorGreaterThan(); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void VectorGreaterThanSingle() { TestVectorGreaterThan(); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void VectorGreaterThanDouble() { TestVectorGreaterThan(); } private void TestVectorGreaterThan() where T : struct, INumber { @@ -1889,10 +1872,8 @@ private void TestVectorGreaterThan() where T : struct, INumber [Fact] public void GreaterThanOrEqualInt64() { TestVectorGreaterThanOrEqual(); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void GreaterThanOrEqualSingle() { TestVectorGreaterThanOrEqual(); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void GreaterThanOrEqualDouble() { TestVectorGreaterThanOrEqual(); } private void TestVectorGreaterThanOrEqual() where T : struct, INumber { @@ -2144,10 +2125,8 @@ private void TestVectorGreaterThanOrEqualAll() where T : struct [Fact] public void LessThanInt64() { TestVectorLessThan(); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void LessThanSingle() { TestVectorLessThan(); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void LessThanDouble() { TestVectorLessThan(); } private void TestVectorLessThan() where T : struct, INumber { @@ -2183,10 +2162,8 @@ private void TestVectorLessThan() where T : struct, INumber [Fact] public void LessThanOrEqualInt64() { TestVectorLessThanOrEqual(); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void LessThanOrEqualSingle() { TestVectorLessThanOrEqual(); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void LessThanOrEqualDouble() { TestVectorLessThanOrEqual(); } private void TestVectorLessThanOrEqual() where T : struct, INumber { @@ -2222,10 +2199,8 @@ private void TestVectorLessThanOrEqual() where T : struct, INumber [Fact] public void LessThanAnyInt64() { TestVectorLessThanAny(); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void LessThanAnySingle() { TestVectorLessThanAny(); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void LessThanAnyDouble() { TestVectorLessThanAny(); } private void TestVectorLessThanAny() where T : struct, INumber { @@ -2550,10 +2525,8 @@ private void TestVectorEqualsAll() where T : struct, INumber [Fact] public void ConditionalSelectInt64() { TestConditionalSelect(); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void ConditionalSelectSingle() { TestConditionalSelect(); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void ConditionalSelectDouble() { TestConditionalSelect(); } private void TestConditionalSelect() where T : struct, INumber { @@ -2604,10 +2577,8 @@ private void TestConditionalSelect() where T : struct, INumber [Fact] public void DotProductInt64() { TestDotProduct(); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void DotProductSingle() { TestDotProduct(); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void DotProductDouble() { TestDotProduct(); } private void TestDotProduct() where T : struct, INumber { @@ -2642,10 +2613,8 @@ private void TestDotProduct() where T : struct, INumber [Fact] public void MaxInt64() { TestMax(); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void MaxSingle() { TestMax(); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void MaxDouble() { TestMax(); } private void TestMax() where T : struct, INumber { @@ -2680,10 +2649,8 @@ private void TestMax() where T : struct, INumber [Fact] public void MinInt64() { TestMin(); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void MinSingle() { TestMin(); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void MinDouble() { TestMin(); } private void TestMin() where T : struct, INumber { @@ -2718,10 +2685,8 @@ private void TestMin() where T : struct, INumber [Fact] public void SquareRootInt64() { TestSquareRoot(-1); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void SquareRootSingle() { TestSquareRoot(6); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void SquareRootDouble() { TestSquareRoot(15); } private void TestSquareRoot(int precision = -1) where T : struct, INumber, IEquatable { @@ -2814,10 +2779,8 @@ public void FloorDouble() [Fact] public void AbsInt64() { TestAbs(); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void AbsSingle() { TestAbs(); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void AbsDouble() { TestAbs(); } private void TestAbs() where T : struct, INumber { @@ -2854,10 +2817,8 @@ private void TestAbs() where T : struct, INumber [Fact] public void MultiplicationReflectionInt64() { TestMultiplicationReflection(); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void MultiplicationReflectionSingle() { TestMultiplicationReflection(); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void MultiplicationReflectionDouble() { TestMultiplicationReflection(); } private void TestMultiplicationReflection() where T : struct, INumber { @@ -2893,10 +2854,8 @@ private void TestMultiplicationReflection() where T : struct, INumber [Fact] public void AdditionReflectionInt64() { TestAdditionReflection(); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void AdditionReflectionSingle() { TestAdditionReflection(); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void AdditionReflectionDouble() { TestAdditionReflection(); } private void TestAdditionReflection() where T : struct, INumber { @@ -2932,10 +2891,8 @@ private void TestAdditionReflection() where T : struct, INumber [Fact] public void DivisionReflectionInt64() { TestDivisionReflection(); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void DivisionReflectionSingle() { TestDivisionReflection(); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void DivisionReflectionDouble() { TestDivisionReflection(); } private void TestDivisionReflection() where T : struct, INumber { diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs index 26c2eb7078598..7ea36b67c970b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs @@ -22,6 +22,7 @@ namespace System.Threading /// concurrently from multiple threads. /// /// + [DebuggerDisplay("IsCancellationRequested = {IsCancellationRequested}")] public class CancellationTokenSource : IDisposable { /// A that's already canceled. diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Thread.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Thread.Unix.cs index a3302b3bedc38..592f0244e011a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Thread.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Thread.Unix.cs @@ -18,22 +18,16 @@ internal static System.Threading.Tasks.Task RegisterWasiPollableHandle(int handl return WasiEventLoop.RegisterWasiPollableHandle(handle, cancellationToken); } - internal static int PollWasiEventLoopUntilResolved(Task mainTask) + internal static T PollWasiEventLoopUntilResolved(Task mainTask) { - while (!mainTask.IsCompleted) - { - WasiEventLoop.DispatchWasiEventLoop(); - } - var exception = mainTask.Exception; - if (exception is not null) - { - throw exception; - } - - return mainTask.Result; + return WasiEventLoop.PollWasiEventLoopUntilResolved(mainTask); } -#endif + internal static void PollWasiEventLoopUntilResolvedVoid(Task mainTask) + { + WasiEventLoop.PollWasiEventLoopUntilResolvedVoid(mainTask); + } +#endif // TARGET_WASI // the closest analog to Sleep(0) on Unix is sched_yield internal static void UninterruptibleSleep0() => Thread.Yield(); diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPoolWorkQueue.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPoolWorkQueue.cs index 279932486e58a..69a59198a40f4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPoolWorkQueue.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPoolWorkQueue.cs @@ -906,10 +906,7 @@ internal static bool Dispatch() // thread because it sees a Determining or Scheduled stage, and the current thread is the last thread processing // work items, the current thread must either see the work item queued by the enqueuer, or it must see a stage of // Scheduled, and try to dequeue again or request another thread. -#if !TARGET_WASI - // TODO https://github.com/dotnet/runtime/issues/104803 Debug.Assert(workQueue._separated.queueProcessingStage == QueueProcessingStage.Scheduled); -#endif workQueue._separated.queueProcessingStage = QueueProcessingStage.Determining; Interlocked.MemoryBarrier(); diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Wasi/WasiEventLoop.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Wasi/WasiEventLoop.cs index e8e7b20dc3473..f2a5d898566cd 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Wasi/WasiEventLoop.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Wasi/WasiEventLoop.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using WasiPollWorld.wit.imports.wasi.io.v0_2_1; using Pollable = WasiPollWorld.wit.imports.wasi.io.v0_2_1.IPoll.Pollable; +using MonotonicClockInterop = WasiPollWorld.wit.imports.wasi.clocks.v0_2_1.MonotonicClockInterop; namespace System.Threading { @@ -14,7 +15,9 @@ internal static class WasiEventLoop // it will be leaked and stay in this list forever. // it will also keep the Pollable handle alive and prevent it from being disposed private static readonly List s_pollables = new(); - private static bool s_tasksCanceled; + private static bool s_checkScheduled; + private static Pollable? s_resolvedPollable; + private static Task? s_mainTask; internal static Task RegisterWasiPollableHandle(int handle, CancellationToken cancellationToken) { @@ -29,18 +32,70 @@ internal static Task RegisterWasiPollable(Pollable pollable, CancellationToken c // this will register the pollable holder into s_pollables var holder = new PollableHolder(pollable, cancellationToken); s_pollables.Add(holder); + + ScheduleCheck(); + return holder.taskCompletionSource.Task; } - // this is not thread safe - internal static void DispatchWasiEventLoop() + + internal static T PollWasiEventLoopUntilResolved(Task mainTask) + { + try + { + s_mainTask = mainTask; + while (!mainTask.IsCompleted) + { + ThreadPoolWorkQueue.Dispatch(); + } + } + finally + { + s_mainTask = null; + } + var exception = mainTask.Exception; + if (exception is not null) + { + throw exception; + } + + return mainTask.Result; + } + + internal static void PollWasiEventLoopUntilResolvedVoid(Task mainTask) + { + try + { + s_mainTask = mainTask; + while (!mainTask.IsCompleted) + { + ThreadPoolWorkQueue.Dispatch(); + } + } + finally + { + s_mainTask = null; + } + + var exception = mainTask.Exception; + if (exception is not null) + { + throw exception; + } + } + + internal static void ScheduleCheck() { - ThreadPoolWorkQueue.Dispatch(); - if (s_tasksCanceled) + if (!s_checkScheduled && s_pollables.Count > 0) { - s_tasksCanceled = false; - return; + s_checkScheduled = true; + ThreadPool.UnsafeQueueUserWorkItem(CheckPollables, null); } + } + + internal static void CheckPollables(object? _) + { + s_checkScheduled = false; var holders = new List(s_pollables.Count); var pending = new List(s_pollables.Count); @@ -58,13 +113,28 @@ internal static void DispatchWasiEventLoop() if (pending.Count > 0) { + var resolvedPollableIndex = -1; + // if there is CPU-bound work to do, we should not block on PollInterop.Poll below + // so we will append pollable resolved in 0ms + // in effect, the PollInterop.Poll would not block us + if (ThreadPool.PendingWorkItemCount > 0 || (s_mainTask != null && s_mainTask.IsCompleted)) + { + s_resolvedPollable ??= MonotonicClockInterop.SubscribeDuration(0); + resolvedPollableIndex = pending.Count; + pending.Add(s_resolvedPollable); + } + var readyIndexes = PollInterop.Poll(pending); for (int i = 0; i < readyIndexes.Length; i++) { uint readyIndex = readyIndexes[i]; - var holder = holders[(int)readyIndex]; - holder.ResolveAndDispose(); + if (resolvedPollableIndex != readyIndex) + { + var holder = holders[(int)readyIndex]; + holder.ResolveAndDispose(); + } } + for (int i = 0; i < holders.Count; i++) { PollableHolder holder = holders[i]; @@ -73,6 +143,8 @@ internal static void DispatchWasiEventLoop() s_pollables.Add(holder); } } + + ScheduleCheck(); } } @@ -112,7 +184,7 @@ public void ResolveAndDispose() } // for GC of abandoned Tasks or for cancellation - private static void CancelAndDispose(object? s) + public static void CancelAndDispose(object? s) { PollableHolder self = (PollableHolder)s!; if (self.isDisposed) @@ -120,11 +192,6 @@ private static void CancelAndDispose(object? s) return; } - // Tell event loop to exit early, giving the application a - // chance to quit if the task(s) it is interested in have - // completed. - s_tasksCanceled = true; - // it will be removed from s_pollables on the next run self.isDisposed = true; self.pollable.Dispose(); diff --git a/src/libraries/System.Private.Uri/src/System/UriExt.cs b/src/libraries/System.Private.Uri/src/System/UriExt.cs index 6f2f61c76721d..ee35d01e96232 100644 --- a/src/libraries/System.Private.Uri/src/System/UriExt.cs +++ b/src/libraries/System.Private.Uri/src/System/UriExt.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Buffers; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; @@ -216,32 +217,49 @@ private void InitializeUri(ParsingError err, UriKind uriKind, out UriFormatExcep } } - // Unescapes entire string and checks if it has unicode chars - // Also checks for sequences that are 3986 Unreserved characters as these should be un-escaped + /// SearchValues for all ASCII characters other than % + private static readonly SearchValues s_asciiOtherThanPercent = SearchValues.Create( + "\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\u0008\u0009\u000A\u000B\u000C\u000D\u000E\u000F" + + "\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001A\u001B\u001C\u001D\u001E\u001F" + + "\u0020\u0021\u0022\u0023\u0024" + "\u0026\u0027\u0028\u0029\u002A\u002B\u002C\u002D\u002E\u002F" + + "\u0030\u0031\u0032\u0033\u0034\u0035\u0036\u0037\u0038\u0039\u003A\u003B\u003C\u003D\u003E\u003F" + + "\u0040\u0041\u0042\u0043\u0044\u0045\u0046\u0047\u0048\u0049\u004A\u004B\u004C\u004D\u004E\u004F" + + "\u0050\u0051\u0052\u0053\u0054\u0055\u0056\u0057\u0058\u0059\u005A\u005B\u005C\u005D\u005E\u005F" + + "\u0060\u0061\u0062\u0063\u0064\u0065\u0066\u0067\u0068\u0069\u006A\u006B\u006C\u006D\u006E\u006F" + + "\u0070\u0071\u0072\u0073\u0074\u0075\u0076\u0077\u0078\u0079\u007A\u007B\u007C\u007D\u007E\u007F"); + + /// + /// Unescapes entire string and checks if it has unicode chars.Also checks for sequences that are 3986 Unreserved characters as these should be un-escaped + /// private static bool CheckForUnicodeOrEscapedUnreserved(string data) { - for (int i = 0; i < data.Length; i++) + int i = data.AsSpan().IndexOfAnyExcept(s_asciiOtherThanPercent); + if (i >= 0) { - char c = data[i]; - if (c == '%') + for ( ; i < data.Length; i++) { - if ((uint)(i + 2) < (uint)data.Length) + char c = data[i]; + if (c == '%') { - char value = UriHelper.DecodeHexChars(data[i + 1], data[i + 2]); - - if (!char.IsAscii(value) || UriHelper.Unreserved.Contains(value)) + if ((uint)(i + 2) < (uint)data.Length) { - return true; - } + char value = UriHelper.DecodeHexChars(data[i + 1], data[i + 2]); + + if (!char.IsAscii(value) || UriHelper.Unreserved.Contains(value)) + { + return true; + } - i += 2; + i += 2; + } + } + else if (c > 0x7F) + { + return true; } - } - else if (c > 0x7F) - { - return true; } } + return false; } diff --git a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector128Tests.cs b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector128Tests.cs index 27955248daac8..09153068d9143 100644 --- a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector128Tests.cs +++ b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector128Tests.cs @@ -36,7 +36,6 @@ internal static void AssertEqual(Vector128 expected, Vector128 a [Fact] [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(Vector128))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/81785", TestPlatforms.Browser)] public unsafe void Vector128IsHardwareAcceleratedTest() { MethodInfo methodInfo = typeof(Vector128).GetMethod("get_IsHardwareAccelerated"); diff --git a/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs b/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs index a64b43d688473..ea3ced24ee08e 100644 --- a/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs +++ b/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs @@ -452,12 +452,40 @@ private static string EmitSearchValues(char[] chars, Dictionary "s_asciiExceptWhiteSpace", "FFFFFFFFFFFF00FC01000078010000F8" => "s_asciiExceptWordChars", + "FFFFFFFFFFDF00FCFFFFFFFFFFFFFFFF" => "s_asciiExceptDigitsAndDash", + "000000000040FF03FEFFFF07FEFFFF07" => "s_asciiLettersAndDigitsAndDot", + "000000000020FF03FEFFFF07FEFFFF07" => "s_asciiLettersAndDigitsAndDash", + "000000000060FF03FEFFFF07FEFFFF07" => "s_asciiLettersAndDigitsAndDashDot", + "000000000040FF03FEFFFF87FEFFFF07" => "s_asciiLettersAndDigitsAndDotUnderscore", + "000000000020FF03FEFFFF87FEFFFF07" => "s_asciiLettersAndDigitsAndDashUnderscore", + "000000000060FF03FEFFFF87FEFFFF07" => "s_asciiLettersAndDigitsAndDashDotUnderscore", + "000000000040FF030000000000000000" => "s_asciiDigitsAndDot", + "000000000020FF030000000000000000" => "s_asciiDigitsAndDash", + "0000000000200000FEFFFF07FEFFFF07" => "s_asciiLettersAndDash", + "0000000000000000FEFFFF87FEFFFF07" => "s_asciiLettersAndUnderscore", + "000000000000FF0300000000FEFFFF07" => "s_asciiLettersLowerAndDigits", + "000000000000FF03FEFFFF0700000000" => "s_asciiLettersUpperAndDigits", + "000000000020FF0300000000FEFFFF07" => "s_asciiLettersLowerAndDigitsAndDash", + _ => $"s_ascii_{hexBitmap.TrimStart('0')}" }; } else { fieldName = GetSHA256FieldName("s_nonAscii_", new string(chars)); + + fieldName = fieldName switch + { + "s_nonAscii_326E1FD0AD567A84CAD13F2BE521A57789829F59D59ABE37F9E111D0182B6601" => "s_asciiLettersAndKelvinSign", + "s_nonAscii_46E3FAA2E94950B9D41E9AB1B570CAB55D04A30009110072B4BC074D57272527" => "s_asciiLettersAndDigitsAndKelvinSign", + "s_nonAscii_2D5586687DC37F0329E3CA4127326E68B5A3A090B13B7834AEA7BFC4EDDE220F" => "s_asciiLettersAndDigitsAndDashKelvinSign", + "s_nonAscii_83AFA3CC45CC4C2D8C316947CFC319199813C7F90226BDF348E2B3236D6237C1" => "s_asciiLettersAndDigitsAndDashDotKelvinSign", + "s_nonAscii_9FA52D3BAECB644578472387D5284CC6F36F408FEB88A04BA674CE14F24D2386" => "s_asciiLettersAndDigitsAndUnderscoreKelvinSign", + "s_nonAscii_D41BEF0BEAFBA32A45D2356E3F1579596F35B7C67CAA9CF7C4B3F2A5422DCA51" => "s_asciiLettersAndDigitsAndDashUnderscoreKelvinSign", + "s_nonAscii_0D7E5600013B3F0349C00277028B6DEA566BB9BAF991CCB7AC92DEC54C4544C1" => "s_asciiLettersAndDigitsAndDashDotUnderscoreKelvinSign", + + _ => fieldName + }; } } diff --git a/src/mono/System.Private.CoreLib/src/System/Threading/ThreadPool.Wasi.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Threading/ThreadPool.Wasi.Mono.cs index bad9fbdbaaddf..0d082fd863cb9 100644 --- a/src/mono/System.Private.CoreLib/src/System/Threading/ThreadPool.Wasi.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Threading/ThreadPool.Wasi.Mono.cs @@ -35,7 +35,7 @@ public static partial class ThreadPool { // Indicates whether the thread pool should yield the thread from the dispatch loop to the runtime periodically so that // the runtime may use the thread for processing other work - internal static bool YieldFromDispatchLoop => false; + internal static bool YieldFromDispatchLoop => true; private const bool IsWorkerTrackingEnabledInConfig = false; diff --git a/src/mono/browser/runtime/jiterpreter-jit-call.ts b/src/mono/browser/runtime/jiterpreter-jit-call.ts index f9ee806540c60..48e9797cb29e8 100644 --- a/src/mono/browser/runtime/jiterpreter-jit-call.ts +++ b/src/mono/browser/runtime/jiterpreter-jit-call.ts @@ -61,7 +61,6 @@ const maxJitQueueLength = 6, let trampBuilder: WasmBuilder; let fnTable: WebAssembly.Table; -let wasmEhSupported: boolean | undefined = undefined; let nextDisambiguateIndex = 0; const fnCache: Array = []; const targetCache: { [target: number]: TrampolineInfo } = {}; @@ -276,18 +275,6 @@ export function mono_interp_jit_wasm_jit_call_trampoline ( mono_interp_flush_jitcall_queue(); } -function getIsWasmEhSupported (): boolean { - if (wasmEhSupported !== undefined) - return wasmEhSupported; - - // Probe whether the current environment can handle wasm exceptions - wasmEhSupported = runtimeHelpers.featureWasmEh === true; - if (!wasmEhSupported) - mono_log_info("Disabling Jiterpreter Exception Handling"); - - return wasmEhSupported; -} - export function mono_interp_flush_jitcall_queue (): void { const jitQueue: TrampolineInfo[] = []; let methodPtr = 0; @@ -336,7 +323,7 @@ export function mono_interp_flush_jitcall_queue (): void { } if (builder.options.enableWasmEh) { - if (!getIsWasmEhSupported()) { + if (!runtimeHelpers.featureWasmEh) { // The user requested to enable wasm EH but it's not supported, so turn the option back off applyOptions({ enableWasmEh: false }); builder.options.enableWasmEh = false; diff --git a/src/mono/browser/runtime/jiterpreter-trace-generator.ts b/src/mono/browser/runtime/jiterpreter-trace-generator.ts index b994927d308d8..fb36b03e2cdfe 100644 --- a/src/mono/browser/runtime/jiterpreter-trace-generator.ts +++ b/src/mono/browser/runtime/jiterpreter-trace-generator.ts @@ -449,10 +449,9 @@ export function generateWasmBody ( if (pruneOpcodes) { // We emit an unreachable opcode so that if execution somehow reaches a pruned opcode, we will abort // This should be impossible anyway but it's also useful to have pruning visible in the wasm - // FIXME: Ideally we would stop generating opcodes after the first unreachable, but that causes v8 to hang if (!hasEmittedUnreachable) builder.appendU8(WasmOpcode.unreachable); - // Each unreachable opcode could generate a bunch of native code in a bad wasm jit so generate nops after it + // Don't generate multiple unreachable opcodes in a row hasEmittedUnreachable = true; } break; @@ -467,7 +466,7 @@ export function generateWasmBody ( } case MintOpcode.MINT_LOCALLOC: { // dest - append_ldloca(builder, getArgU16(ip, 1)); + append_ldloca(builder, getArgU16(ip, 1), 0); // len append_ldloc(builder, getArgU16(ip, 2), WasmOpcode.i32_load); // frame @@ -648,10 +647,12 @@ export function generateWasmBody ( // locals[ip[1]] = &locals[ip[2]] const offset = getArgU16(ip, 2), flag = isAddressTaken(builder, offset), - destOffset = getArgU16(ip, 1); + destOffset = getArgU16(ip, 1), + // Size value stored for us by emit_compacted_instruction so we can do invalidation + size = getArgU16(ip, 3); if (!flag) mono_log_error(`${traceName}: Expected local ${offset} to have address taken flag`); - append_ldloca(builder, offset); + append_ldloca(builder, offset, size); append_stloc_tail(builder, destOffset, WasmOpcode.i32_store); // Record this ldloca as a known constant so that later uses of it turn into a lea, // and the wasm runtime can constant fold them with other constants. It's not uncommon @@ -875,9 +876,8 @@ export function generateWasmBody ( } case MintOpcode.MINT_LD_DELEGATE_METHOD_PTR: { - // FIXME: ldloca invalidation size - append_ldloca(builder, getArgU16(ip, 1), 8); - append_ldloca(builder, getArgU16(ip, 2), 8); + append_ldloca(builder, getArgU16(ip, 1), 4); + append_ldloca(builder, getArgU16(ip, 2), 4); builder.callImport("ld_del_ptr"); break; } @@ -1280,6 +1280,21 @@ export function generateWasmBody ( break; } + case MintOpcode.MINT_NEWARR: { + builder.block(); + append_ldloca(builder, getArgU16(ip, 1), 4); + const vtable = get_imethod_data(frame, getArgU16(ip, 3)); + builder.i32_const(vtable); + append_ldloc(builder, getArgU16(ip, 2), WasmOpcode.i32_load); + builder.callImport("newarr"); + // If the newarr operation succeeded, continue, otherwise bailout + builder.appendU8(WasmOpcode.br_if); + builder.appendULeb(0); + append_bailout(builder, ip, BailoutReason.AllocFailed); + builder.endBlock(); + break; + } + case MintOpcode.MINT_NEWOBJ_INLINED: { builder.block(); // MonoObject *o = mono_gc_alloc_obj (vtable, m_class_get_instance_size (vtable->klass)); @@ -1368,7 +1383,9 @@ export function generateWasmBody ( (builder.callHandlerReturnAddresses.length <= maxCallHandlerReturnAddresses) ) { // mono_log_info(`endfinally @0x${(ip).toString(16)}. return addresses:`, builder.callHandlerReturnAddresses.map(ra => (ra).toString(16))); - // FIXME: Clean this codegen up + // FIXME: Replace this with a chain of selects to more efficiently map from RA -> index, then + // a single jump table at the end to jump to the right place. This will generate much smaller + // code and be able to handle a larger number of return addresses. // Load ret_ip const clauseIndex = getArgU16(ip, 1), clauseDataOffset = get_imethod_clause_data_offset(frame, clauseIndex); @@ -1957,10 +1974,7 @@ function append_stloc_tail (builder: WasmBuilder, offset: number, opcodeOrPrefix // Pass bytesInvalidated=0 if you are reading from the local and the address will never be // used for writes -function append_ldloca (builder: WasmBuilder, localOffset: number, bytesInvalidated?: number) { - if (typeof (bytesInvalidated) !== "number") - bytesInvalidated = 512; - // FIXME: We need to know how big this variable is so we can invalidate the whole space it occupies +function append_ldloca (builder: WasmBuilder, localOffset: number, bytesInvalidated: number) { if (bytesInvalidated > 0) invalidate_local_range(localOffset, bytesInvalidated); builder.lea("pLocals", localOffset); @@ -2461,7 +2475,8 @@ function emit_sfieldop ( builder.ptr_const(pStaticData); // src append_ldloca(builder, localOffset, 0); - // FIXME: Use mono_gc_wbarrier_set_field_internal + // We don't need to use gc_wbarrier_set_field_internal here because there's no object + // reference, interp does a raw write builder.callImport("copy_ptr"); return true; case MintOpcode.MINT_LDSFLD_VT: { @@ -2888,7 +2903,6 @@ function emit_branch ( ); cwraps.mono_jiterp_boost_back_branch_target(destination); - // FIXME: Should there be a safepoint here? append_bailout(builder, destination, BailoutReason.BackwardBranch); modifyCounter(JiterpCounter.BackBranchesNotEmitted, 1); return true; @@ -3526,19 +3540,6 @@ function emit_arrayop (builder: WasmBuilder, frame: NativePointer, ip: MintOpcod return true; } -let wasmSimdSupported: boolean | undefined; - -function getIsWasmSimdSupported (): boolean { - if (wasmSimdSupported !== undefined) - return wasmSimdSupported; - - wasmSimdSupported = runtimeHelpers.featureWasmSimd === true; - if (!wasmSimdSupported) - mono_log_info("Disabling Jiterpreter SIMD"); - - return wasmSimdSupported; -} - function get_import_name ( builder: WasmBuilder, typeName: string, functionPtr: number @@ -3557,7 +3558,7 @@ function emit_simd ( ): boolean { // First, if compiling an intrinsic attempt to emit the special vectorized implementation // We only do this if SIMD is enabled since we'll be using the v128 opcodes. - if (builder.options.enableSimd && getIsWasmSimdSupported()) { + if (builder.options.enableSimd && runtimeHelpers.featureWasmSimd) { switch (argCount) { case 2: if (emit_simd_2(builder, ip, index)) @@ -3577,7 +3578,7 @@ function emit_simd ( // Fall back to a mix of non-vectorized wasm and the interpreter's implementation of the opcodes switch (opcode) { case MintOpcode.MINT_SIMD_V128_LDC: { - if (builder.options.enableSimd && getIsWasmSimdSupported()) { + if (builder.options.enableSimd && runtimeHelpers.featureWasmSimd) { builder.local("pLocals"); const view = localHeapViewU8().slice(ip + 4, ip + 4 + sizeOfV128); builder.v128_const(view); @@ -4034,7 +4035,6 @@ function emit_atomics ( if (!builder.options.enableAtomics) return false; - // FIXME: memory barrier might be worthwhile to implement // FIXME: We could probably unify most of the xchg/cmpxchg implementation into one implementation const xchg = xchgTable[opcode]; diff --git a/src/mono/browser/runtime/jiterpreter.ts b/src/mono/browser/runtime/jiterpreter.ts index f665d0cccc7dc..996e7ed34f9d1 100644 --- a/src/mono/browser/runtime/jiterpreter.ts +++ b/src/mono/browser/runtime/jiterpreter.ts @@ -272,6 +272,7 @@ function getTraceImports () { ["ckovr_u4", "overflow_check_i4", getRawCwrap("mono_jiterp_overflow_check_u4")], importDef("newobj_i", getRawCwrap("mono_jiterp_try_newobj_inlined")), importDef("newstr", getRawCwrap("mono_jiterp_try_newstr")), + importDef("newarr", getRawCwrap("mono_jiterp_try_newarr")), importDef("ld_del_ptr", getRawCwrap("mono_jiterp_ld_delegate_method_ptr")), importDef("ldtsflda", getRawCwrap("mono_jiterp_ldtsflda")), importDef("conv", getRawCwrap("mono_jiterp_conv")), @@ -465,6 +466,15 @@ function initialize_builder (builder: WasmBuilder) { }, WasmValtype.i32, true ); + builder.defineType( + "newarr", + { + "ppDestination": WasmValtype.i32, + "vtable": WasmValtype.i32, + "length": WasmValtype.i32, + }, + WasmValtype.i32, true + ); builder.defineType( "localloc", { @@ -841,18 +851,6 @@ function generate_wasm ( // Get the exported trace function const fn = traceInstance.exports[traceName]; - // FIXME: Before threading can be supported, we will need to ensure that - // once we assign a function pointer index to a given trace, the trace is - // broadcast to all the JS workers and compiled + installed at the appropriate - // index in every worker's function pointer table. This also means that we - // would need to fill empty slots with a dummy function when growing the table - // so that any erroneous ENTERs will skip the opcode instead of crashing due - // to calling a null function pointer. - // Table grow operations will need to be synchronized between workers somehow, - // probably by storing the table size in a volatile global or something so that - // we know the range of indexes available to us and can ensure that threads - // independently jitting traces will not stomp on each other and all threads - // have a globally consistent view of which function pointer maps to each trace. rejected = false; let idx: number; @@ -985,7 +983,6 @@ export function mono_interp_tier_prepare_jiterpreter ( if (!mostRecentOptions) mostRecentOptions = getOptions(); - // FIXME: We shouldn't need this check if (!mostRecentOptions.enableTraces) return JITERPRETER_NOT_JITTED; else if (mostRecentOptions.wasmBytesLimit <= getCounter(JiterpCounter.BytesGenerated)) diff --git a/src/mono/browser/runtime/startup.ts b/src/mono/browser/runtime/startup.ts index 4d07e712358b0..834ceb81f2f7b 100644 --- a/src/mono/browser/runtime/startup.ts +++ b/src/mono/browser/runtime/startup.ts @@ -128,6 +128,9 @@ async function instantiateWasmWorker ( successCallback: InstantiateWasmSuccessCallback ): Promise { if (!WasmEnableThreads) return; + + await ensureUsedWasmFeatures(); + // wait for the config to arrive by message from the main thread await loaderHelpers.afterConfigLoaded.promise; diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c index 12f2cdd50350e..1dda6c2164891 100644 --- a/src/mono/mono/mini/interp/interp.c +++ b/src/mono/mono/mini/interp/interp.c @@ -7657,7 +7657,8 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MINT_IN_CASE(MINT_LDLOCA_S) LOCAL_VAR (ip [1], gpointer) = locals + ip [2]; - ip += 3; + // ip[3] reserved for size data for jiterpreter + ip += 4; MINT_IN_BREAK; #define MOV(argtype1,argtype2) \ diff --git a/src/mono/mono/mini/interp/jiterpreter-opcode-values.h b/src/mono/mono/mini/interp/jiterpreter-opcode-values.h index a509b8471cfa9..d360bceb0fc32 100644 --- a/src/mono/mono/mini/interp/jiterpreter-opcode-values.h +++ b/src/mono/mono/mini/interp/jiterpreter-opcode-values.h @@ -98,6 +98,7 @@ OP(MINT_BOX, NORMAL) OP(MINT_BOX_VT, NORMAL) OP(MINT_UNBOX, NORMAL) OP(MINT_NEWSTR, NORMAL) +OP(MINT_NEWARR, NORMAL) OP(MINT_LD_DELEGATE_METHOD_PTR, NORMAL) OP(MINT_LDTSFLDA, NORMAL) OP(MINT_ADD_MUL_I4_IMM, NORMAL) diff --git a/src/mono/mono/mini/interp/jiterpreter.c b/src/mono/mono/mini/interp/jiterpreter.c index 362f01a2390b2..b63ec1b284e48 100644 --- a/src/mono/mono/mini/interp/jiterpreter.c +++ b/src/mono/mono/mini/interp/jiterpreter.c @@ -202,6 +202,18 @@ mono_jiterp_try_newstr (MonoString **destination, int length) { return *destination != 0; } +EMSCRIPTEN_KEEPALIVE int +mono_jiterp_try_newarr (MonoArray **destination, MonoVTable *vtable, int length) { + if (length < 0) + return 0; + ERROR_DECL(error); + *destination = mono_array_new_specific_checked (vtable, length, error); + if (!is_ok (error)) + *destination = 0; + mono_error_cleanup (error); // FIXME: do not swallow the error + return *destination != 0; +} + EMSCRIPTEN_KEEPALIVE int mono_jiterp_gettype_ref ( MonoObject **destination, MonoObject **source diff --git a/src/mono/mono/mini/interp/mintops.def b/src/mono/mono/mini/interp/mintops.def index 11e65fb97ade6..5e2c41d60c47f 100644 --- a/src/mono/mono/mini/interp/mintops.def +++ b/src/mono/mono/mini/interp/mintops.def @@ -128,7 +128,11 @@ OPDEF(MINT_MOV_8_2, "mov.8.2", 5, 0, 0, MintOpPair2) OPDEF(MINT_MOV_8_3, "mov.8.3", 7, 0, 0, MintOpPair3) OPDEF(MINT_MOV_8_4, "mov.8.4", 9, 0, 0, MintOpPair4) -OPDEF(MINT_LDLOCA_S, "ldloca.s", 3, 1, 0, MintOpUShortInt) +// NOTE: We reserve an extra ushort at the end of this specifically to communicate information +// to the jiterpreter about how large the local is so that invalidation can be correct. +// FIXME: genmintops.py is way too simple to handle this having a different size on different targets, +// so it's got a size of 4 everywhere. +OPDEF(MINT_LDLOCA_S, "ldloca.s", 4, 1, 0, MintOpUShortInt) OPDEF(MINT_LDIND_I1, "ldind.i1", 3, 1, 1, MintOpNoArgs) OPDEF(MINT_LDIND_U1, "ldind.u1", 3, 1, 1, MintOpNoArgs) @@ -838,7 +842,7 @@ OPDEF(MINT_INTRINS_WIDEN_ASCII_TO_UTF16, "intrins_widen_ascii_to_utf16", 5, 1, 3 OPDEF(MINT_METADATA_UPDATE_LDFLDA, "metadata_update.ldflda", 5, 1, 1, MintOpTwoShorts) // This ifdef is fine because genmintops.py is generating output for HOST_BROWSER -#if HOST_BROWSER +#ifdef HOST_BROWSER OPDEF(MINT_TIER_PREPARE_JITERPRETER, "tier_prepare_jiterpreter", 4, 0, 0, MintOpShortAndInt) OPDEF(MINT_TIER_NOP_JITERPRETER, "tier_nop_jiterpreter", 4, 0, 0, MintOpShortAndInt) OPDEF(MINT_TIER_ENTER_JITERPRETER, "tier_enter_jiterpreter", 4, 0, 0, MintOpShortAndInt) diff --git a/src/mono/mono/mini/interp/transform.c b/src/mono/mono/mini/interp/transform.c index 4b1865b8310b5..22c5518a82c04 100644 --- a/src/mono/mono/mini/interp/transform.c +++ b/src/mono/mono/mini/interp/transform.c @@ -9241,6 +9241,12 @@ emit_compacted_instruction (TransformData *td, guint16* start_ip, InterpInst *in } else if (opcode == MINT_LDLOCA_S) { // This opcode receives a local but it is not viewed as a sreg since we don't load the value *ip++ = GINT_TO_UINT16 (get_var_offset (td, ins->sregs [0])); + +#if HOST_BROWSER + // We reserve an extra 2 bytes at the end of ldloca_s so the jiterpreter knows how large + // the var is when taking its address so that it can invalidate a properly sized range. + *ip++ = GINT_TO_UINT16 (td->vars [ins->sregs [0]].size); +#endif } int left = interp_get_ins_length (ins) - GPTRDIFF_TO_INT(ip - start_ip); diff --git a/src/mono/sample/wasi/http-p2/Program.cs b/src/mono/sample/wasi/http-p2/Program.cs index e940c0a4100b6..9bf6140161db5 100644 --- a/src/mono/sample/wasi/http-p2/Program.cs +++ b/src/mono/sample/wasi/http-p2/Program.cs @@ -13,6 +13,7 @@ public static class WasiMainWrapper { public static async Task MainAsync(string[] args) { + _ = Task.Delay(100_000_000); // create a task that will not complete before main await Task.Delay(100); GC.Collect(); // test that Pollable->Task is not collected until resolved @@ -78,7 +79,7 @@ public static int Main(string[] args) return PollWasiEventLoopUntilResolved((Thread)null!, MainAsync(args)); [UnsafeAccessor(UnsafeAccessorKind.StaticMethod, Name = "PollWasiEventLoopUntilResolved")] - static extern int PollWasiEventLoopUntilResolved(Thread t, Task mainTask); + static extern T PollWasiEventLoopUntilResolved(Thread t, Task mainTask); } } diff --git a/src/mono/wasi/testassets/Http.cs b/src/mono/wasi/testassets/Http.cs index 49bc33f28fa3c..87b1f8437f71f 100644 --- a/src/mono/wasi/testassets/Http.cs +++ b/src/mono/wasi/testassets/Http.cs @@ -83,6 +83,6 @@ public static int Main(string[] args) return PollWasiEventLoopUntilResolved((Thread)null!, MainAsync(args)); [UnsafeAccessor(UnsafeAccessorKind.StaticMethod, Name = "PollWasiEventLoopUntilResolved")] - static extern int PollWasiEventLoopUntilResolved(Thread t, Task mainTask); + static extern T PollWasiEventLoopUntilResolved(Thread t, Task mainTask); } } diff --git a/src/native/corehost/fxr/fx_resolver.cpp b/src/native/corehost/fxr/fx_resolver.cpp index e78bd63eca109..c109fa257121c 100644 --- a/src/native/corehost/fxr/fx_resolver.cpp +++ b/src/native/corehost/fxr/fx_resolver.cpp @@ -540,7 +540,7 @@ StatusCode fx_resolver_t::resolve_frameworks_for_app( _X("Architecture: %s"), app_display_name, get_current_arch_name()); - display_missing_framework_error(resolution_failure.missing.get_fx_name(), resolution_failure.missing.get_fx_version(), pal::string_t(), dotnet_root, app_config.get_is_multilevel_lookup_disabled()); + display_missing_framework_error(resolution_failure.missing.get_fx_name(), resolution_failure.missing.get_fx_version(), dotnet_root, app_config.get_is_multilevel_lookup_disabled()); break; case StatusCode::FrameworkCompatFailure: display_incompatible_framework_error(resolution_failure.incompatible_higher.get_fx_version(), resolution_failure.incompatible_lower); diff --git a/src/native/corehost/fxr/fx_resolver.h b/src/native/corehost/fxr/fx_resolver.h index 466decd846fc9..9abfd706baadc 100644 --- a/src/native/corehost/fxr/fx_resolver.h +++ b/src/native/corehost/fxr/fx_resolver.h @@ -64,7 +64,6 @@ class fx_resolver_t static void display_missing_framework_error( const pal::string_t& fx_name, const pal::string_t& fx_version, - const pal::string_t& fx_dir, const pal::string_t& dotnet_root, bool disable_multilevel_lookup); static void display_incompatible_framework_error( diff --git a/src/native/corehost/fxr/fx_resolver.messages.cpp b/src/native/corehost/fxr/fx_resolver.messages.cpp index e87cd6d0fbacb..a922858ae5b39 100644 --- a/src/native/corehost/fxr/fx_resolver.messages.cpp +++ b/src/native/corehost/fxr/fx_resolver.messages.cpp @@ -3,6 +3,7 @@ #include "fx_resolver.h" #include "framework_info.h" +#include "install_info.h" /** * When the framework is referenced more than once in a non-compatible way, display detailed error message @@ -92,23 +93,9 @@ void fx_resolver_t::display_summary_of_frameworks( void fx_resolver_t::display_missing_framework_error( const pal::string_t& fx_name, const pal::string_t& fx_version, - const pal::string_t& fx_dir, const pal::string_t& dotnet_root, bool disable_multilevel_lookup) { - std::vector framework_infos; - pal::string_t fx_ver_dirs; - if (fx_dir.length()) - { - fx_ver_dirs = fx_dir; - framework_info::get_all_framework_infos(get_directory(fx_dir), fx_name.c_str(), disable_multilevel_lookup, &framework_infos); - } - else - { - fx_ver_dirs = dotnet_root; - } - - framework_info::get_all_framework_infos(dotnet_root, fx_name.c_str(), disable_multilevel_lookup, &framework_infos); // Display the error message about missing FX. if (fx_version.length()) @@ -122,6 +109,8 @@ void fx_resolver_t::display_missing_framework_error( trace::error(_X(".NET location: %s\n"), dotnet_root.c_str()); + std::vector framework_infos; + framework_info::get_all_framework_infos(dotnet_root, fx_name.c_str(), disable_multilevel_lookup, &framework_infos); if (framework_infos.size()) { trace::error(_X("The following frameworks were found:")); @@ -135,6 +124,30 @@ void fx_resolver_t::display_missing_framework_error( trace::error(_X("No frameworks were found.")); } + std::vector>> other_arch_framework_infos; + install_info::enumerate_other_architectures( + [&](pal::architecture arch, const pal::string_t& install_location, bool is_registered) + { + std::vector other_arch_infos; + framework_info::get_all_framework_infos(install_location, fx_name.c_str(), disable_multilevel_lookup, &other_arch_infos); + if (!other_arch_infos.empty()) + { + other_arch_framework_infos.push_back(std::make_pair(arch, std::move(other_arch_infos))); + } + }); + if (!other_arch_framework_infos.empty()) + { + trace::error(_X("\nThe following frameworks for other architectures were found:")); + for (const auto& arch_info_pair : other_arch_framework_infos) + { + trace::error(_X(" %s"), get_arch_name(arch_info_pair.first)); + for (const framework_info& info : arch_info_pair.second) + { + trace::error(_X(" %s at [%s]"), info.version.as_str().c_str(), info.path.c_str()); + } + } + } + pal::string_t url = get_download_url(fx_name.c_str(), fx_version.c_str()); trace::error( _X("\n") diff --git a/src/native/corehost/fxr/install_info.cpp b/src/native/corehost/fxr/install_info.cpp index ff231938db0d8..281457f115820 100644 --- a/src/native/corehost/fxr/install_info.cpp +++ b/src/native/corehost/fxr/install_info.cpp @@ -31,7 +31,7 @@ bool install_info::print_environment(const pal::char_t* leading_whitespace) return found_any; } -bool install_info::print_other_architectures(const pal::char_t* leading_whitespace) +bool install_info::enumerate_other_architectures(std::function callback) { bool found_any = false; for (uint32_t i = 0; i < static_cast(pal::architecture::__last); ++i) @@ -47,13 +47,22 @@ bool install_info::print_other_architectures(const pal::char_t* leading_whitespa { found_any = true; remove_trailing_dir_separator(&install_location); + callback(arch, install_location, is_registered); + } + } + + return found_any; +} + +bool install_info::print_other_architectures(const pal::char_t* leading_whitespace) +{ + return enumerate_other_architectures( + [&](pal::architecture arch, const pal::string_t& install_location, bool is_registered) + { trace::println(_X("%s%-5s [%s]"), leading_whitespace, get_arch_name(arch), install_location.c_str()); if (is_registered) { trace::println(_X("%s registered at [%s]"), leading_whitespace, pal::get_dotnet_self_registered_config_location(arch).c_str()); } - } - } - - return found_any; + }); } diff --git a/src/native/corehost/fxr/install_info.h b/src/native/corehost/fxr/install_info.h index 3a100486b8f3e..3f9d591026848 100644 --- a/src/native/corehost/fxr/install_info.h +++ b/src/native/corehost/fxr/install_info.h @@ -5,9 +5,11 @@ #define __INSTALL_INFO_H__ #include "pal.h" +#include namespace install_info { + bool enumerate_other_architectures(std::function callback); bool print_environment(const pal::char_t* leading_whitespace); bool print_other_architectures(const pal::char_t* leading_whitespace); }; diff --git a/src/native/corehost/hostmisc/utils.h b/src/native/corehost/hostmisc/utils.h index 5d782a070f8b8..52c6754d290a7 100644 --- a/src/native/corehost/hostmisc/utils.h +++ b/src/native/corehost/hostmisc/utils.h @@ -10,13 +10,6 @@ #include #include -#if defined(_WIN32) -#define DOTNET_CORE_INSTALL_PREREQUISITES_URL _X("https://go.microsoft.com/fwlink/?linkid=798306") -#elif defined(TARGET_OSX) -#define DOTNET_CORE_INSTALL_PREREQUISITES_URL _X("https://go.microsoft.com/fwlink/?linkid=2063366") -#else -#define DOTNET_CORE_INSTALL_PREREQUISITES_URL _X("https://go.microsoft.com/fwlink/?linkid=2063370") -#endif #define DOTNET_CORE_DOWNLOAD_URL _X("https://aka.ms/dotnet/download") #define DOTNET_CORE_APPLAUNCH_URL _X("https://aka.ms/dotnet-core-applaunch") diff --git a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs index 1814cba54eb18..34cc69f775283 100644 --- a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs +++ b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs @@ -127,13 +127,14 @@ private bool StripAssembly(ITaskItem assemblyItem) try { - if(!AssemblyStripper.AssemblyStripper.TryStripAssembly(assemblyFile, outputPath)) + if (!AssemblyStripper.AssemblyStripper.TryStripAssembly(assemblyFile, outputPath)) { Log.LogMessage(MessageImportance.Low, $"[ILStrip] Skipping {assemblyFile} because it is not a managed assembly."); } else { - _processedAssemblies.GetOrAdd(assemblyItem.ItemSpec, GetTrimmedAssemblyItem(assemblyItem, outputPath, assemblyFile)); + var fullPath = assemblyItem.GetMetadata("FullPath"); + _processedAssemblies.GetOrAdd(fullPath, GetTrimmedAssemblyItem(assemblyItem, outputPath, assemblyFile)); } } catch (Exception ex) diff --git a/src/tasks/WasmAppBuilder/JoinedString.cs b/src/tasks/WasmAppBuilder/JoinedString.cs new file mode 100644 index 0000000000000..28d411e652273 --- /dev/null +++ b/src/tasks/WasmAppBuilder/JoinedString.cs @@ -0,0 +1,170 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.IO; +using System.Runtime.CompilerServices; +using System.Collections; +using System.Collections.Generic; +using System.Text; + +namespace JoinedString; + +internal static class JoinedStringExtensions +{ + public static JoinedStringEnumerable Join(this IEnumerable list, string separator) + => JoinedStringEnumerable.Join(list, separator); + public static JoinedStringEnumerable Join(this IEnumerable list, string separator, Func formatter) + => JoinedStringEnumerable.Join(list, separator, formatter); + public static JoinedStringEnumerable Join(this IEnumerable list, string separator, Func formatter) + => JoinedStringEnumerable.Join(list, separator, formatter); + + public static JoinedList Join(this IList list, string separator) + => new JoinedList(list, separator, (item, _) => $"{item}"); + public static JoinedList Join(this IList list, string separator, Func formatter) + => new JoinedList(list, separator, (str, _) => formatter(str)); + public static JoinedList Join(this IList list, string separator, Func formatter) + => new JoinedList(list, separator, formatter); +} + + +internal sealed record JoinedList(IList items, string separator, Func formatter) +{ + public IEnumerator GetEnumerator() + { + for (int i = 0; i < items.Count; i++) + { + if (i != 0) + yield return separator; + yield return formatter(items[i], i); + } + } + + public override string ToString() + { + var sb = new StringBuilder(); + foreach (var item in this) + { + sb.Append(item); + } + return sb.ToString(); + } +} + +internal sealed class JoinedStringEnumerable : IEnumerable +{ + private readonly IEnumerable _values; + + private JoinedStringEnumerable(IEnumerable values) + { + _values = values; + } + + public static JoinedStringEnumerable Join(IEnumerable values, string separator) + => new JoinedStringEnumerable(JoinInternal(values, separator, (x, _) => x)); + + public static JoinedStringEnumerable Join(IEnumerable values, string separator, Func format) + => new JoinedStringEnumerable(JoinInternal(values, separator, (x, _) => format(x))); + + public static JoinedStringEnumerable Join(IEnumerable values, string separator, Func format) + => new JoinedStringEnumerable(JoinInternal(values, separator, format)); + + private static IEnumerable JoinInternal(IEnumerable values, string separator, Func format) + { + int index = 0; + foreach (var value in values) + { + if (index != 0) + yield return separator; + yield return format(value, index++); + } + } + + public IEnumerator GetEnumerator() => _values.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)_values).GetEnumerator(); + + public override string ToString() + { + var sb = new StringBuilder(); + foreach (var item in this) + { + sb.Append(item); + } + return sb.ToString(); + } +} + +internal sealed class JoinedStringStreamWriter : StreamWriter +{ + + // since we are intentionally using multi-line string writes, + // we want to capture the compile-time new line + private string CompileTimeNewLine = +@" +"; + + public JoinedStringStreamWriter(Stream stream) : base(stream) + { + NewLine = CompileTimeNewLine; + } + + public JoinedStringStreamWriter(string path, bool append) : base(path, append) + { + NewLine = CompileTimeNewLine; + } + +#if NET8_0_OR_GREATER +#pragma warning disable CA1822 // Mark members as static +#pragma warning disable IDE0060 // Remove unused parameter + public void Write([InterpolatedStringHandlerArgument("")] JoinedStringWriterHandler builder) + { + // The builder writes directly to the writer + } +#pragma warning restore IDE0060 +#pragma warning restore CA1822 +#endif +} + +#if NET8_0_OR_GREATER +[InterpolatedStringHandler] +internal ref struct JoinedStringWriterHandler +{ + private JoinedStringStreamWriter _writer; + +#pragma warning disable IDE0060 + public JoinedStringWriterHandler(int literalLength, int formattedCount, JoinedStringStreamWriter writer) + { + writer.Flush(); + _writer = writer; + } +#pragma warning restore IDE0060 + + public void AppendLiteral(string s) => _writer.Write(s); + public void AppendFormatted(T value) => _writer.Write(value); + public void AppendFormatted(Span value) => _writer.Write(value); + public void AppendFormatted(char[] buffer, int index, int count) => _writer.Write(buffer, index, count); + public void AppendFormatted(string format, object? arg0, object? arg1, object? arg2) => _writer.Write(format, arg0, arg1, arg2); + + public void AppendFormatted(JoinedStringEnumerable list) + { + foreach (var item in list) + { + _writer.Write(item); + } + } + + public void AppendFormatted(JoinedList list) + { + foreach (var item in list) + { + _writer.Write(item); + } + } + + public override string ToString() + { + _writer.Flush(); + return ""; + } +} +#endif diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_105619/Runtime_105619.cs b/src/tests/JIT/Regression/JitBlue/Runtime_105619/Runtime_105619.cs new file mode 100644 index 0000000000000..1956903c95f15 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_105619/Runtime_105619.cs @@ -0,0 +1,246 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// Generated by Fuzzlyn v2.1 on 2024-07-28 15:37:46 +// Run on Arm Linux +// Seed: 8024459297219020330 +// Reduced from 3285.8 KiB to 12.2 KiB in 01:46:03 +// Hits JIT assert in Release: +// Assertion failed 'varDsc->IsAlwaysAliveInMemory() || ((regSet.GetMaskVars() & regMask) == 0)' in 'Program:Main(Fuzzlyn.ExecutionServer.IRuntime)' during 'Generate code' (IL size 7170; hash 0xade6b36b; FullOpts) +// +// File: /__w/1/s/src/coreclr/jit/codegencommon.cpp Line: 664 +// +using System; +using System.Runtime.CompilerServices; +using Xunit; + +public interface I1 +{ +} + +public struct S0 +{ + public double F0; + public sbyte F1; + public ulong F2; + public int F3; + public ulong F4; + public ulong F6; + public int F7; + public long F8; + public S0(double f0, ulong f2, ulong f4, float f5, ulong f6, int f7, long f8) : this() + { + } +} + +public struct S1 +{ + public int F0; + public S0 F2; + public S0 F3; + public S0 F4; + public S1(int f0, double f1, S0 f2, S0 f3, S0 f4) : this() + { + } +} + +public struct S2 : I1 +{ + public S1 F2; + public ushort F4; + public S1 F6; + public S1 F7; + public S2(sbyte f0, ulong f1, S1 f2, ushort f4, byte f5, S1 f6, S1 f7) : this() + { + } +} + +public class C0 +{ + public S1 F1; + public C0(S1 f1) + { + } +} + +public struct S3 : I1 +{ + public S3(short f0) : this() + { + } +} + +public struct S4 : I1 +{ + public S3 F0; + public S2 F1; + public S4(S3 f0, S2 f1, float f2, S0 f3, int f5) : this() + { + } +} + +public struct S5 +{ + public C0 F0; + public S5(C0 f0, S1 f3) : this() + { + } +} + +public class C1 +{ + public bool F1; +} + +public class Program +{ + public static IRuntime s_rt; + public static S2 s_13; + public static S1 s_18; + public static bool[] s_22; + public static C0 s_24; + public static ushort[, ] s_31; + public static S1 s_35; + public static bool s_37; + public static S5[] s_44; + public static S4 s_54; + public static S1 s_58; + public static C1[, ] s_59; + public static S4 s_60; + public static S2 s_88; + public static S2[] s_90; + + [Fact] + public static void TestEntryPoint() + { + try + { + CollectibleALC alc = new CollectibleALC(); + System.Reflection.Assembly asm = alc.LoadFromAssemblyPath(System.Reflection.Assembly.GetExecutingAssembly().Location); + System.Reflection.MethodInfo mi = asm.GetType(typeof(Program).FullName).GetMethod(nameof(MainInner)); + System.Type runtimeTy = asm.GetType(typeof(Runtime).FullName); + mi.Invoke(null, new object[] { System.Activator.CreateInstance(runtimeTy) }); + } catch {} + } + +// Allow reflection lookup on public method +#pragma warning disable xUnit1013 + public static void MainInner(IRuntime rt) + { + S0 vr8 = default(S0); + if (s_59[0, 0].F1) + { + bool[] vr9 = new bool[] + { + true + }; + s_88 = new S2(s_54.F1.F2.F4.F1, s_24.F1.F2.F4--, new S1(s_35.F2.F3, 0, new S0(-2, 0, 0, 0, 11218621709493063492UL, 450420498, 0), s_60.F1.F7.F2, new S0(0, 0, 0, 0, 0, 1, 0)), s_13.F4--, (byte)s_31[0, 0], new S1(0, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0)), s_54.F1.F2); + vr9[0] = vr9[0]; + } + + s_rt.WriteLine("c_6973", vr8.F2); + s_rt.WriteLine("c_6975", vr8.F4); + s_rt.WriteLine("c_6978", vr8.F7); + I1[] vr10 = new I1[] + { + new S2(0, 0, new S1(0, 0, new S0(0, 0, 0, -3.4028235E+38F, 0, 0, 0), new S0(0, 0, 0, 1, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0)), 0, 0, new S1(1, 0, new S0(0, 0, 0, 0, 0, 1, 0), new S0(0, 0, 0, 0, 0, 1, 0), new S0(0, 0, 0, 0, 0, 0, 0)), new S1(0, 0, new S0(0, 0, 16728947367172946933UL, 0, 0, 0, 0), new S0(1, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0))), + new S3(0), + new S2(0, 0, new S1(0, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0)), 1, 0, new S1(0, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 2102657202, 0)), new S1(0, 0, new S0(0, 0, 0, 0, 0, 1, 0), new S0(0, 16794536930986757818UL, 0, 0, 0, 0, 0), new S0(0, 0, 11911619636908597430UL, 0, 0, 0, 0))), + new S3(0), + new S2(0, 0, new S1(-2147483647, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0)), 1, 0, new S1(0, -2, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(1, 0, 0, 0, 0, 0, 0)), new S1(1, 1, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 1, 0))), + new S2(0, 0, new S1(0, -1, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0)), 0, 0, new S1(-1, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, -3.4028235E+38F, 0, 0, 0), new S0(0, 0, 0, 0, 0, 1, 0)), new S1(0, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0))), + new S4(new S3(0), new S2(1, 0, new S1(0, 1, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 1, 0)), 1, 0, new S1(1, 0, new S0(0, 0, 0, 0, 0, 1, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 1, 0)), new S1(0, 0, new S0(0, 0, 0, 0, 0, 1, 0), new S0(1, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0))), 0, new S0(0, 0, 0, 0, 0, 0, 0), 0) + }; + var vr11 = new S3(0); + var vr12 = s_44[0].F0.F1.F3.F0; + M75(vr11, vr12); + if (s_22[0]) + { + S3 vr13 = new S3(0); + try + { + var vr14 = s_54.F0; + var vr15 = s_18.F4.F0; + S3 vr23 = vr14; + } + finally + { + var vr16 = new S3(0); + var vr17 = s_58.F4.F0--; + M75(vr16, vr17); + if (s_37) + { + for (int vr18 = 0; vr18 < 2; vr18++) + { + var vr19 = new S3(0); + vr10[0] = new S4(new S3(0), new S2(1, 5461410436353764379UL, new S1(0, 0, new S0(0, 18446744073709551614UL, 0, 0, 17533718527758593297UL, 0, 0), new S0(0, 8592301711847430801UL, 0, 0, 0, 0, 0), new S0(-1, 7862269010569978854UL, 0, 0, 0, 0, 0)), 0, 0, new S1(0, 0, new S0(0, 3156588052453432602UL, 0, 0, 0, 810788132, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0)), new S1(1, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 15070356010362475091UL, 0, 0))), 0, new S0(0, 0, 0, 0, 0, 0, 0), 0); + vr10 = new I1[] + { + new S2(1, 0, new S1(0, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, -3.4028235E+38F, 0, -1, 0), new S0(0, 7703692348755595801UL, 0, 0, 0, 0, 0)), 0, 0, new S1(1, 1.7976931348623157E+308, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 1, 0)), new S1(0, -1, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 3991586019811875011UL, 0, 0, 0, -2147483648, 0))), + new S4(new S3(-1), new S2(0, 9890997199408041578UL, new S1(0, 0, new S0(0, 0, 0, 0, 0, 1, 0), new S0(0, 0, 0, 0, 0, 0, -7424873608279851173L), new S0(0, 0, 9698347484967702837UL, 0, 0, 0, 0)), 0, 0, new S1(0, 0, new S0(1, 0, 0, 0, 0, 0, 8154649548600176800L), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, -9223372036854775808L)), new S1(0, 0, new S0(1, 0, 0, 0, 0, 0, 0), new S0(0, 778004003835070330UL, 0, 0, 0, 0, 0), new S0(0, 0, 8658698987098108904UL, 0, 0, 0, 0))), 0, new S0(0, 0, 0, 0, 0, 0, 0), 956596481), + new S4(new S3(0), new S2(0, 453734974695362841UL, new S1(0, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, -8941433507005588199L)), 0, 1, new S1(0, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 1, 0)), new S1(0, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 10794758865549560580UL, 0, 7077610171127139841UL, 1, 0), new S0(1, 0, 0, 0, 0, 0, 0))), 0, new S0(1, 0, 0, 0, 17621340021635995622UL, 0, 0), 1), + new S2(0, 0, new S1(0, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(1, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0)), 0, 0, new S1(0, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0)), new S1(0, 0, new S0(1, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0))), + new S2(0, 6130557987521252430UL, new S1(0, -2, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 1, 0), new S0(1, 12555188232274105334UL, 0, 0, 0, 0, 0)), 1, 0, new S1(0, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0)), new S1(0, 0, new S0(0, 1828388993980413842UL, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 5800380996067047058UL, 0, 0))), + new S3(1) + }; + s_rt.WriteLine("c_7152", vr18); + } + + S0 vr20 = new S0(0, 0, 0, 0, 0, 0, 0); + C0 vr21 = new C0(new S1(0, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0))); + s_rt.WriteLine("c_7159", vr20.F6); + s_rt.WriteLine("c_7164", vr21.F1.F0); + s_rt.WriteLine("c_7168", vr21.F1.F2.F2); + s_rt.WriteLine("c_7170", vr21.F1.F2.F4); + s_rt.WriteLine("c_7173", vr21.F1.F2.F7); + s_rt.WriteLine("c_7176", vr21.F1.F3.F1); + s_rt.WriteLine("c_7177", vr21.F1.F3.F2); + s_rt.WriteLine("c_7181", vr21.F1.F3.F6); + s_rt.WriteLine("c_7185", vr21.F1.F4.F1); + s_rt.WriteLine("c_7191", vr21.F1.F4.F7); + s_rt.WriteLine("c_7192", vr21.F1.F4.F8); + } + + s_54.F1.F2.F0 = s_90[0].F6.F0++; + } + + var vr22 = new S5(new C0(new S1(0, 0, new S0(-2, 0, 0, 0, 0, 0, 0), new S0(1, 0, 0, 0, 0, -1, 0), new S0(0, 0, 0, 0, 0, 0, 0))), new S1(0, 0, new S0(-1, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0))); + } + + vr10 = new I1[] + { + new S4(new S3(-18643), new S2(0, 0, new S1(1, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 11398096482162480173UL, 0, 0, 0, 9223372036854775806L), new S0(0, 0, 0, 0, 0, 2134113955, 0)), 0, 0, new S1(0, 0, new S0(0, 0, 15971873843035984033UL, 0, 5979847448536525346UL, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(1, 0, 0, 0, 11276959574309188693UL, 0, 0)), new S1(0, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 1, 0), new S0(0, 0, 0, 0, 0, 0, 0))), 0, new S0(0, 0, 0, 0, 0, 0, 0), 0), + new S3(1), + new S3(0), + new S4(new S3(0), new S2(0, 0, new S1(0, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 1, 0), new S0(0, 0, 0, 0, 0, 1, 0)), 1, 0, new S1(0, 0, new S0(0, 0, 0, 0, 11829847737932804605UL, 0, 0), new S0(1, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0)), new S1(0, -2, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 9919258226402299883UL, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0))), 0, new S0(0, 0, 0, 0, 0, 1, 0), 0), + new S2(0, 0, new S1(0, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0)), 0, 0, new S1(0, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0)), new S1(-1, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 1, 0), new S0(0, 0, 0, 0, 0, 0, 0))), + new S4(new S3(0), new S2(0, 0, new S1(0, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0)), 0, 0, new S1(0, 1, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, -1, 0), new S0(0, 0, 0, 0, 0, 0, 0)), new S1(0, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(1, 0, 0, 0, 0, 0, 0))), 0, new S0(0, 0, 0, 0, 0, 1, 0), 0), + new S4(new S3(0), new S2(0, 0, new S1(0, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0)), 0, 0, new S1(0, 0, new S0(1, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0)), new S1(0, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0))), 0, new S0(1, 0, 0, 0, 0, 0, 0), 0), + new S3(0), + new S3(0), + new S3(0) + }; + } +#pragma warning restore xUnit1013 + + private static void M75(S3 argThis, double arg1) + { + } +} + +public interface IRuntime +{ + void WriteLine(string site, T value); +} + +public class Runtime : IRuntime +{ + public void WriteLine(string site, T value) => System.Console.WriteLine(value); +} + +public class CollectibleALC : System.Runtime.Loader.AssemblyLoadContext +{ + public CollectibleALC() : base(true) + { + } +} \ No newline at end of file diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_105619/Runtime_105619.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_105619/Runtime_105619.csproj new file mode 100644 index 0000000000000..de6d5e08882e8 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_105619/Runtime_105619.csproj @@ -0,0 +1,8 @@ + + + True + + + + + diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_105620/Runtime_105620.cs b/src/tests/JIT/Regression/JitBlue/Runtime_105620/Runtime_105620.cs new file mode 100644 index 0000000000000..486afcffb12c0 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_105620/Runtime_105620.cs @@ -0,0 +1,199 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// Generated by Fuzzlyn v2.1 on 2024-07-28 20:48:11 +// Run on Arm Linux +// Seed: 7638843082097772896 +// Reduced from 1010.6 KiB to 5.3 KiB in 00:18:13 +// Hits JIT assert in Release: +// Assertion failed 'baseRegUsed == reg2' in 'Program:M48(S0,S3,S2,S2)' during 'Generate code' (IL size 2164; hash 0x03983244; FullOpts) +// +// File: /__w/1/s/src/coreclr/jit/emitarm.cpp Line: 3919 +// +using System; +using System.Runtime.CompilerServices; +using Xunit; + +public struct S0 +{ + public ulong F0; + public int F1; + public long F2; + public uint F3; + public byte F4; + public float F5; + public sbyte F6; + public double F7; + public sbyte F8; +} + +public struct S1 +{ + public double F0; + public short F1; + public bool F2; + public S0 F3; + public sbyte F4; + public ushort F5; + public ulong F6; + public int F7; + public S0 F8; +} + +public struct S2 +{ + public double F0; + public S0 F1; + public S1 F2; + public ushort F4; + public S2(S1 f2) + { + F2 = f2; + } +} + +public class C0 +{ +} + +public struct S3 +{ + public double F0; + public float F1; + public ushort F2; + public long F3; + public S1 F4; + public S2 F5; + public S2 F6; + public uint F7; + public S2 F8; + public S3(S2 f5, S2 f8) : this() + { + F5 = f5; + F8 = f8; + } +} + +public struct S4 +{ + public double F0; + public double F1; + public float F2; + public ulong F3; + public bool F4; + public int F5; + public bool F6; + public S3 F7; + public float F8; + public S4(S3 f7) + { + F7 = f7; + } +} + +public class Program +{ + public static IRuntime s_rt; + public static S4 s_2; + public static S4 s_3; + public static S4[][] s_6; + public static S3[] s_23 = new S3[] + { + new S3(new S2(new S1()), new S2(new S1())) + }; + + [Fact] + public static void TestEntryPoint() + { + try + { + var vr8 = new S4(new S3(new S2(new S1()), new S2(new S1()))); + var vr9 = s_23[0].F6.F1; + var vr13 = s_2.F7; + var vr14 = vr8.F7.F6; + var vr15 = vr8.F7.F6; + M48(vr9, vr13, vr14, vr15); + } catch {} + } + + private static void M48(S0 argThis, S3 arg0, S2 arg1, S2 arg2) + { + arg2.F2.F0 = arg2.F2.F0; + S4 var1 = new S4(new S3(new S2(new S1()), new S2(new S1()))); + var1.F7.F5.F2.F8.F5 = s_6[0][0].F7.F8.F2.F3.F5; + var vr2 = new C0(); + M49(0, vr2, ref arg2.F2.F1, ref s_3.F7, ref arg1.F1.F8); + S4 var2 = var1; + s_rt.WriteLine(System.BitConverter.DoubleToUInt64Bits(var2.F7.F0)); + s_rt.WriteLine(System.BitConverter.SingleToUInt32Bits(var2.F7.F1)); + s_rt.WriteLine(var2.F7.F2); + s_rt.WriteLine(var2.F7.F3); + s_rt.WriteLine(System.BitConverter.DoubleToUInt64Bits(var2.F7.F4.F0)); + s_rt.WriteLine(var2.F7.F4.F1); + s_rt.WriteLine(var2.F7.F4.F2); + s_rt.WriteLine(var2.F7.F4.F3.F0); + s_rt.WriteLine(var2.F7.F4.F3.F1); + s_rt.WriteLine(var2.F7.F4.F3.F2); + s_rt.WriteLine(var2.F7.F4.F3.F3); + s_rt.WriteLine(var2.F7.F4.F3.F4); + s_rt.WriteLine(System.BitConverter.SingleToUInt32Bits(var2.F7.F4.F3.F5)); + s_rt.WriteLine(var2.F7.F4.F3.F6); + s_rt.WriteLine(System.BitConverter.DoubleToUInt64Bits(var2.F7.F4.F3.F7)); + s_rt.WriteLine(var2.F7.F4.F3.F8); + s_rt.WriteLine(var2.F7.F4.F4); + s_rt.WriteLine(var2.F7.F4.F5); + s_rt.WriteLine(var2.F7.F4.F6); + s_rt.WriteLine(var2.F7.F4.F7); + s_rt.WriteLine(var2.F7.F4.F8.F0); + s_rt.WriteLine(var2.F7.F4.F8.F1); + s_rt.WriteLine(var2.F7.F4.F8.F2); + s_rt.WriteLine(var2.F7.F4.F8.F3); + s_rt.WriteLine(var2.F7.F4.F8.F4); + s_rt.WriteLine(System.BitConverter.SingleToUInt32Bits(var2.F7.F4.F8.F5)); + s_rt.WriteLine(var2.F7.F4.F8.F6); + s_rt.WriteLine(System.BitConverter.DoubleToUInt64Bits(var2.F7.F4.F8.F7)); + s_rt.WriteLine(var2.F7.F4.F8.F8); + s_rt.WriteLine(System.BitConverter.DoubleToUInt64Bits(var2.F7.F5.F0)); + s_rt.WriteLine(var2.F7.F5.F1.F0); + s_rt.WriteLine(var2.F7.F5.F1.F1); + s_rt.WriteLine(var2.F7.F5.F1.F2); + s_rt.WriteLine(var2.F7.F5.F1.F3); + s_rt.WriteLine(var2.F7.F5.F1.F4); + s_rt.WriteLine(System.BitConverter.SingleToUInt32Bits(var2.F7.F5.F1.F5)); + s_rt.WriteLine(var2.F7.F5.F1.F6); + s_rt.WriteLine(System.BitConverter.DoubleToUInt64Bits(var2.F7.F5.F1.F7)); + s_rt.WriteLine(var2.F7.F5.F1.F8); + s_rt.WriteLine(System.BitConverter.DoubleToUInt64Bits(var2.F7.F5.F2.F0)); + s_rt.WriteLine(var2.F7.F5.F2.F1); + s_rt.WriteLine(var2.F7.F5.F2.F2); + s_rt.WriteLine(var2.F7.F5.F2.F3.F0); + s_rt.WriteLine(var2.F7.F5.F2.F3.F1); + s_rt.WriteLine(var2.F7.F5.F2.F3.F2); + s_rt.WriteLine(var2.F7.F5.F2.F3.F3); + s_rt.WriteLine(var2.F7.F5.F2.F3.F4); + s_rt.WriteLine(System.BitConverter.SingleToUInt32Bits(var2.F7.F5.F2.F3.F5)); + s_rt.WriteLine(var2.F7.F5.F2.F3.F6); + s_rt.WriteLine(System.BitConverter.DoubleToUInt64Bits(var2.F7.F5.F2.F3.F7)); + s_rt.WriteLine(var2.F7.F5.F2.F3.F8); + s_rt.WriteLine(var2.F7.F5.F2.F4); + s_rt.WriteLine(var2.F7.F5.F2.F5); + s_rt.WriteLine(var2.F7.F5.F2.F6); + s_rt.WriteLine(var2.F7.F5.F2.F7); + s_rt.WriteLine(var2.F7.F5.F2.F8.F0); + } + + private static void M49(short arg0, C0 arg2, ref short arg3, ref S3 arg4, ref sbyte arg5) + { + s_rt.WriteLine(arg0); + } +} + +public interface IRuntime +{ + void WriteLine(T value); +} + +public class Runtime : IRuntime +{ + public void WriteLine(T value) => System.Console.WriteLine(value); +} \ No newline at end of file diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_105620/Runtime_105620.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_105620/Runtime_105620.csproj new file mode 100644 index 0000000000000..de6d5e08882e8 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_105620/Runtime_105620.csproj @@ -0,0 +1,8 @@ + + + True + + + + + diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_106869/Runtime_106869.cs b/src/tests/JIT/Regression/JitBlue/Runtime_106869/Runtime_106869.cs new file mode 100644 index 0000000000000..b4b9856c79595 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_106869/Runtime_106869.cs @@ -0,0 +1,59 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Xunit; +using System.Runtime.CompilerServices; + +// Generated by Fuzzlyn v2.3 on 2024-08-23 10:25:51 +// Run on Arm64 Windows +// Seed: 13938901376337307772-vectort,vector64,vector128,armsve +// Reduced from 210.5 KiB to 1.1 KiB in 00:02:19 +// Hits JIT assert in Release: +// Assertion failed 'nestedOp2->OperIsHWIntrinsic()' in 'Program:Main(Fuzzlyn.ExecutionServer.IRuntime)' during 'Lowering nodeinfo' (IL size 119; hash 0xade6b36b; FullOpts) +// +// File: C:\dev\dotnet\runtime2\src\coreclr\jit\lowerarmarch.cpp Line: 4062 +// +using System; +using System.Numerics; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +public struct S0 +{ + public ulong F5; +} + +public class C0 +{ + public int F1; +} + +public class Runtime_1068867 +{ + public static S0 s_7; + public static byte s_14; + + [Fact] + public static void TestEntryPoint() + { + if (Sve.IsSupported) + { + var vr12 = new C0(); + var vr14 = vr12.F1; + var vr15 = Vector128.CreateScalar(vr14).AsVector(); + var vr16 = Vector128.CreateScalar(0).AsVector(); + var vr17 = Vector128.CreateScalar(0).AsVector(); + var vr18 = Vector128.CreateScalar(0).AsVector(); + var vr19 = Vector128.CreateScalar(1).AsVector(); + var vr20 = Sve.ConditionalSelect(vr17, vr18, vr19); + var vr21 = Vector128.CreateScalar(0).AsVector(); + var vr22 = Sve.ConditionalSelect(vr16, vr20, vr21); + Consume(vr22); + } + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static void Consume(T val) + { + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_106869/Runtime_106869.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_106869/Runtime_106869.csproj new file mode 100644 index 0000000000000..1352ebe3277bc --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_106869/Runtime_106869.csproj @@ -0,0 +1,9 @@ + + + True + $(NoWarn),SYSLIB5003 + + + + +