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/eng/pipelines/coreclr/runtime-nativeaot-outerloop.yml b/eng/pipelines/coreclr/runtime-nativeaot-outerloop.yml index 494601a890df1..c39c6d81a45b9 100644 --- a/eng/pipelines/coreclr/runtime-nativeaot-outerloop.yml +++ b/eng/pipelines/coreclr/runtime-nativeaot-outerloop.yml @@ -156,7 +156,6 @@ extends: # # CoreCLR NativeAOT checked build and Pri0 tests - # Only when CoreCLR is changed # - template: /eng/pipelines/common/platform-matrix.yml parameters: @@ -189,3 +188,37 @@ extends: parameters: testGroup: innerloop liveLibrariesBuildConfig: Release + + # + # CoreCLR NativeAOT checked build and Pri0 tests + # Test windows_x64 with CET and CFG + # + - template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/common/global-build-job.yml + helixQueuesTemplate: /eng/pipelines/coreclr/templates/helix-queues-setup.yml + helixQueueGroup: cet + buildConfig: Checked + platforms: + - windows_x64 + variables: + - name: timeoutPerTestInMinutes + value: 60 + - name: timeoutPerTestCollectionInMinutes + value: 180 + jobParameters: + timeoutInMinutes: 300 # doesn't normally take this long, but we have had Helix queues backed up for over an hour + nameSuffix: NativeAOT_Pri0_CET_CFG + buildArgs: -s clr.aot+libs -rc $(_BuildConfig) -lc Release /p:RunAnalyzers=false + postBuildSteps: + - template: /eng/pipelines/coreclr/nativeaot-post-build-steps.yml + parameters: + creator: dotnet-bot + testBuildArgs: 'nativeaot /p:IlcUseServerGc=false /p:ControlFlowGuard=Guard' + liveLibrariesBuildConfig: Release + testRunNamePrefixSuffix: NativeAOT_Pri0_CET_CFG_$(_BuildConfig) + extraVariablesTemplates: + - template: /eng/pipelines/common/templates/runtimes/test-variables.yml + parameters: + testGroup: innerloop + liveLibrariesBuildConfig: Release \ No newline at end of file diff --git a/eng/pipelines/libraries/fuzzing/deploy-to-onefuzz.yml b/eng/pipelines/libraries/fuzzing/deploy-to-onefuzz.yml index 8d0590c992196..49e7e517d9c33 100644 --- a/eng/pipelines/libraries/fuzzing/deploy-to-onefuzz.yml +++ b/eng/pipelines/libraries/fuzzing/deploy-to-onefuzz.yml @@ -105,6 +105,14 @@ extends: SYSTEM_ACCESSTOKEN: $(System.AccessToken) displayName: Send JsonDocumentFuzzer to OneFuzz + - task: onefuzz-task@0 + inputs: + onefuzzOSes: 'Windows' + env: + onefuzzDropDirectory: $(fuzzerProject)/deployment/NrbfDecoderFuzzer + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + displayName: Send NrbfDecoderFuzzer to OneFuzz + - task: onefuzz-task@0 inputs: onefuzzOSes: 'Windows' diff --git a/src/coreclr/System.Private.CoreLib/src/System/Exception.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Exception.CoreCLR.cs index 79944b1cca8e6..1029f3e570e33 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Exception.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Exception.CoreCLR.cs @@ -117,9 +117,6 @@ internal void InternalPreserveStackTrace() [MethodImpl(MethodImplOptions.InternalCall)] private static extern void PrepareForForeignExceptionRaise(); - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern object? GetFrozenStackTrace(Exception exception); - [MethodImpl(MethodImplOptions.InternalCall)] internal static extern uint GetExceptionCount(); @@ -226,9 +223,14 @@ public DispatchState( } } + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ExceptionNative_GetFrozenStackTrace")] + private static partial void GetFrozenStackTrace(ObjectHandleOnStack exception, ObjectHandleOnStack stackTrace); + internal DispatchState CaptureDispatchState() { - object? stackTrace = GetFrozenStackTrace(this); + Exception _this = this; + object? stackTrace = null; + GetFrozenStackTrace(ObjectHandleOnStack.Create(ref _this), ObjectHandleOnStack.Create(ref stackTrace)); return new DispatchState(stackTrace, _remoteStackTraceString, _ipForWatsonBuckets, _watsonBuckets); diff --git a/src/coreclr/System.Private.CoreLib/src/System/GC.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/GC.CoreCLR.cs index 1bd94635a26c7..f8246642b9e61 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/GC.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/GC.CoreCLR.cs @@ -103,8 +103,8 @@ internal enum GC_ALLOC_FLAGS GC_ALLOC_PINNED_OBJECT_HEAP = 64, }; - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern Array AllocateNewArray(IntPtr typeHandle, int length, GC_ALLOC_FLAGS flags); + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "GCInterface_AllocateNewArray")] + private static partial void AllocateNewArray(IntPtr typeHandlePtr, int length, GC_ALLOC_FLAGS flags, ObjectHandleOnStack ret); [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "GCInterface_GetTotalMemory")] private static partial long GetTotalMemory(); @@ -791,16 +791,25 @@ public static unsafe T[] AllocateUninitializedArray(int length, bool pinned = { return new T[length]; } - #endif } - // Runtime overrides GC_ALLOC_ZEROING_OPTIONAL if the type contains references, so we don't need to worry about that. - GC_ALLOC_FLAGS flags = GC_ALLOC_FLAGS.GC_ALLOC_ZEROING_OPTIONAL; - if (pinned) - flags |= GC_ALLOC_FLAGS.GC_ALLOC_PINNED_OBJECT_HEAP; + return AllocateNewArrayWorker(length, pinned); + + [MethodImpl(MethodImplOptions.NoInlining)] + static T[] AllocateNewArrayWorker(int length, bool pinned) + { + // Runtime overrides GC_ALLOC_ZEROING_OPTIONAL if the type contains references, so we don't need to worry about that. + GC_ALLOC_FLAGS flags = GC_ALLOC_FLAGS.GC_ALLOC_ZEROING_OPTIONAL; + if (pinned) + { + flags |= GC_ALLOC_FLAGS.GC_ALLOC_PINNED_OBJECT_HEAP; + } - return Unsafe.As(AllocateNewArray(RuntimeTypeHandle.ToIntPtr(typeof(T[]).TypeHandle), length, flags)); + T[]? result = null; + AllocateNewArray(RuntimeTypeHandle.ToIntPtr(typeof(T[]).TypeHandle), length, flags, ObjectHandleOnStack.Create(ref result)); + return result!; + } } /// @@ -818,7 +827,9 @@ public static T[] AllocateArray(int length, bool pinned = false) // T[] rathe flags = GC_ALLOC_FLAGS.GC_ALLOC_PINNED_OBJECT_HEAP; } - return Unsafe.As(AllocateNewArray(RuntimeTypeHandle.ToIntPtr(typeof(T[]).TypeHandle), length, flags)); + T[]? result = null; + AllocateNewArray(RuntimeTypeHandle.ToIntPtr(typeof(T[]).TypeHandle), length, flags, ObjectHandleOnStack.Create(ref result)); + return result!; } [MethodImpl(MethodImplOptions.InternalCall)] 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..1ebaa04f8f681 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) { @@ -588,7 +586,7 @@ private CultureInfo GetLocale() [MethodImpl(MethodImplOptions.InternalCall)] private static extern bool FCallIsDynamic(RuntimeAssembly assembly); - public override bool IsDynamic => FCallIsDynamic(GetNativeHandle()); + public override bool IsDynamic => FCallIsDynamic(this); [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_GetSimpleName")] private static partial void GetSimpleName(QCallAssembly assembly, StringHandleOnStack retSimpleName); @@ -701,8 +699,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 +727,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 d7d83ba51ac0c..486e5a505abeb 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 @@ -58,6 +58,9 @@ public sealed partial class Thread // but those types of changes may race with the reset anyway, so this field doesn't need to be synchronized. private bool _mayNeedResetForThreadPool; + // Set in unmanaged and read in managed code. + private bool _isDead; + private Thread() { } public int ManagedThreadId @@ -74,7 +77,7 @@ internal ThreadHandle GetNativeHandle() // This should never happen under normal circumstances. if (thread == IntPtr.Zero) { - throw new ArgumentException(null, SR.Argument_InvalidHandle); + throw new ThreadStateException(SR.Argument_InvalidHandle); } return new ThreadHandle(thread); @@ -211,13 +214,25 @@ public extern bool IsThreadPoolThread internal set; } + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ThreadNative_SetPriority")] + [return: MarshalAs(UnmanagedType.Bool)] + private static partial void SetPriority(ObjectHandleOnStack thread, int priority); + /// Returns the priority of the thread. public ThreadPriority Priority { - get => (ThreadPriority)GetPriorityNative(); + get + { + if (_isDead) + { + throw new ThreadStateException(SR.ThreadState_Dead_Priority); + } + return (ThreadPriority)_priority; + } set { - SetPriorityNative((int)value); + Thread _this = this; + SetPriority(ObjectHandleOnStack.Create(ref _this), (int)value); if (value != ThreadPriority.Normal) { _mayNeedResetForThreadPool = true; @@ -225,12 +240,6 @@ public ThreadPriority Priority } } - [MethodImpl(MethodImplOptions.InternalCall)] - private extern int GetPriorityNative(); - - [MethodImpl(MethodImplOptions.InternalCall)] - private extern void SetPriorityNative(int priority); - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ThreadNative_GetCurrentOSThreadId")] private static partial ulong GetCurrentOSThreadId(); @@ -243,21 +252,31 @@ public ThreadPriority Priority [MethodImpl(MethodImplOptions.InternalCall)] private extern int GetThreadStateNative(); - public ApartmentState GetApartmentState() => -#if FEATURE_COMINTEROP_APARTMENT_SUPPORT - (ApartmentState)GetApartmentStateNative(); -#else // !FEATURE_COMINTEROP_APARTMENT_SUPPORT - ApartmentState.Unknown; -#endif // FEATURE_COMINTEROP_APARTMENT_SUPPORT - /// /// An unstarted thread can be marked to indicate that it will host a /// single-threaded or multi-threaded apartment. /// #if FEATURE_COMINTEROP_APARTMENT_SUPPORT + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ThreadNative_GetApartmentState")] + private static partial int GetApartmentState(ObjectHandleOnStack t); + + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ThreadNative_SetApartmentState")] + private static partial int SetApartmentState(ObjectHandleOnStack t, int state); + + public ApartmentState GetApartmentState() + { + Thread _this = this; + return (ApartmentState)GetApartmentState(ObjectHandleOnStack.Create(ref _this)); + } + private bool SetApartmentStateUnchecked(ApartmentState state, bool throwOnError) { - ApartmentState retState = (ApartmentState)SetApartmentStateNative((int)state); + ApartmentState retState; + lock (this) // This lock is only needed when the this is not the current thread. + { + Thread _this = this; + retState = (ApartmentState)SetApartmentState(ObjectHandleOnStack.Create(ref _this), (int)state); + } // Special case where we pass in Unknown and get back MTA. // Once we CoUninitialize the thread, the OS will still @@ -282,12 +301,9 @@ private bool SetApartmentStateUnchecked(ApartmentState state, bool throwOnError) return true; } - [MethodImpl(MethodImplOptions.InternalCall)] - internal extern int GetApartmentStateNative(); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal extern int SetApartmentStateNative(int state); #else // FEATURE_COMINTEROP_APARTMENT_SUPPORT + public ApartmentState GetApartmentState() => ApartmentState.Unknown; + private static bool SetApartmentStateUnchecked(ApartmentState state, bool throwOnError) { if (state != ApartmentState.Unknown) @@ -331,6 +347,10 @@ public void Interrupt() [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ThreadNative_Interrupt")] private static partial void Interrupt(ThreadHandle t); + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ThreadNative_Join")] + [return: MarshalAs(UnmanagedType.Bool)] + private static partial bool Join(ObjectHandleOnStack thread, int millisecondsTimeout); + /// /// Waits for the thread to die or for timeout milliseconds to elapse. /// @@ -338,11 +358,20 @@ public void Interrupt() /// Returns true if the thread died, or false if the wait timed out. If /// -1 is given as the parameter, no timeout will occur. /// - /// if timeout < -1 (Timeout.Infinite) + /// if timeout < -1 (Timeout.Infinite) /// if the thread is interrupted while waiting /// if the thread has not been started yet - [MethodImpl(MethodImplOptions.InternalCall)] - public extern bool Join(int millisecondsTimeout); + public bool Join(int millisecondsTimeout) + { + // Validate the timeout + if (millisecondsTimeout < 0 && millisecondsTimeout != Timeout.Infinite) + { + throw new ArgumentOutOfRangeException(nameof(millisecondsTimeout), SR.ArgumentOutOfRange_NeedNonNegOrNegative1); + } + + Thread _this = this; + return Join(ObjectHandleOnStack.Create(ref _this), millisecondsTimeout); + } /// /// Max value to be passed into for optimal delaying. This value is normalized to be 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 be5ee49e10b69..6309533648bb2 100644 --- a/src/coreclr/debug/daccess/dacdbiimpl.cpp +++ b/src/coreclr/debug/daccess/dacdbiimpl.cpp @@ -3672,7 +3672,7 @@ HRESULT DacDbiInterfaceImpl::GetLoaderHeapMemoryRanges(DacDbiArrayListGetLoaderAllocator(); + PTR_LoaderAllocator pGlobalAllocator = SystemDomain::GetGlobalLoaderAllocator(); _ASSERTE(pGlobalAllocator); EnumerateMemRangesForLoaderAllocator(pGlobalAllocator, &memoryRanges); diff --git a/src/coreclr/debug/daccess/enummem.cpp b/src/coreclr/debug/daccess/enummem.cpp index be3c1123ea416..7840bb29070cd 100644 --- a/src/coreclr/debug/daccess/enummem.cpp +++ b/src/coreclr/debug/daccess/enummem.cpp @@ -743,7 +743,7 @@ HRESULT ClrDataAccess::EnumMemDumpAppDomainInfo(CLRDataEnumMemoryFlags flags) if (flags == CLRDATA_ENUM_MEM_HEAP2) { - SystemDomain::System()->GetLoaderAllocator()->EnumMemoryRegions(flags); + SystemDomain::GetGlobalLoaderAllocator()->EnumMemoryRegions(flags); } AppDomain* appDomain = AppDomain::GetCurrentDomain(); diff --git a/src/coreclr/debug/daccess/request.cpp b/src/coreclr/debug/daccess/request.cpp index bbd2b96c9ba37..2be13b91e98aa 100644 --- a/src/coreclr/debug/daccess/request.cpp +++ b/src/coreclr/debug/daccess/request.cpp @@ -2838,7 +2838,7 @@ ClrDataAccess::GetAppDomainData(CLRDATA_ADDRESS addr, struct DacpAppDomainData * ZeroMemory(appdomainData, sizeof(DacpAppDomainData)); appdomainData->AppDomainPtr = PTR_CDADDR(pBaseDomain); - PTR_LoaderAllocator pLoaderAllocator = pBaseDomain->GetLoaderAllocator(); + PTR_LoaderAllocator pLoaderAllocator = SystemDomain::GetGlobalLoaderAllocator(); appdomainData->pHighFrequencyHeap = HOST_CDADDR(pLoaderAllocator->GetHighFrequencyHeap()); appdomainData->pLowFrequencyHeap = HOST_CDADDR(pLoaderAllocator->GetLowFrequencyHeap()); appdomainData->pStubHeap = HOST_CDADDR(pLoaderAllocator->GetStubHeap()); @@ -4065,8 +4065,7 @@ ClrDataAccess::TraverseVirtCallStubHeap(CLRDATA_ADDRESS pAppDomain, VCSHeapType SOSDacEnter(); - BaseDomain* pBaseDomain = PTR_BaseDomain(TO_TADDR(pAppDomain)); - VirtualCallStubManager *pVcsMgr = pBaseDomain->GetLoaderAllocator()->GetVirtualCallStubManager(); + VirtualCallStubManager *pVcsMgr = SystemDomain::GetGlobalLoaderAllocator()->GetVirtualCallStubManager(); if (!pVcsMgr) { hr = E_POINTER; @@ -4111,8 +4110,8 @@ HRESULT ClrDataAccess::GetDomainLoaderAllocator(CLRDATA_ADDRESS domainAddress, C SOSDacEnter(); - PTR_BaseDomain pDomain = PTR_BaseDomain(TO_TADDR(domainAddress)); - *pLoaderAllocator = pDomain != nullptr ? HOST_CDADDR(pDomain->GetLoaderAllocator()) : 0; + // The one and only app domain uses the global loader allocator + *pLoaderAllocator = HOST_CDADDR(SystemDomain::GetGlobalLoaderAllocator()); SOSDacLeave(); return hr; diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index 20cfda9282651..58eb8614b2f59 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -14787,7 +14787,7 @@ gc_heap::wait_for_gc_done(int32_t timeOut) while (gc_heap::gc_started) { #ifdef MULTIPLE_HEAPS - wait_heap = GCHeap::GetHeap(heap_select::select_heap(NULL))->pGenGCHeap; + wait_heap = g_heaps[heap_select::select_heap(NULL)]; dprintf(2, ("waiting for the gc_done_event on heap %d", wait_heap->heap_number)); #endif // MULTIPLE_HEAPS diff --git a/src/coreclr/gc/handletablescan.cpp b/src/coreclr/gc/handletablescan.cpp index e5b27da8e621d..276e865518b23 100644 --- a/src/coreclr/gc/handletablescan.cpp +++ b/src/coreclr/gc/handletablescan.cpp @@ -1427,7 +1427,14 @@ PTR_TableSegment CALLBACK StandardSegmentIterator(PTR_HandleTable pTable, PTR_Ta #ifndef DACCESS_COMPILE // re-sort the block chains if necessary if (pNextSegment && pNextSegment->fResortChains) + { + // Since this operation can rewrite segment state, it needs to synchronize with any racing + // threads that might be concurrently allocating null handle table slots while running in + // preemptive mode (which happens, e.g., during Thread construction when a native thread + // first enters the runtime). + CrstHolder ch(&pTable->Lock); SegmentResortChains(pNextSegment); + } #endif // return the segment we found diff --git a/src/coreclr/gc/objecthandle.cpp b/src/coreclr/gc/objecthandle.cpp index 7f7f3ec1d5463..6f3bb7a52fa33 100644 --- a/src/coreclr/gc/objecthandle.cpp +++ b/src/coreclr/gc/objecthandle.cpp @@ -1105,7 +1105,7 @@ void Ref_TraceNormalRoots(uint32_t condemned, uint32_t maxgen, ScanContext* sc, // promote objects pointed to by strong handles // during ephemeral GCs we also want to promote the ones pointed to by sizedref handles. - uint32_t types[2] = { + uint32_t types[] = { HNDTYPE_STRONG, #ifdef FEATURE_SIZED_REF_HANDLES HNDTYPE_SIZEDREF diff --git a/src/coreclr/hosts/corerun/corerun.hpp b/src/coreclr/hosts/corerun/corerun.hpp index 5ce0f0b285238..0adcdce234814 100644 --- a/src/coreclr/hosts/corerun/corerun.hpp +++ b/src/coreclr/hosts/corerun/corerun.hpp @@ -455,7 +455,7 @@ namespace pal #else // !__APPLE__ // Use procfs to detect if there is a tracer process. // See https://www.kernel.org/doc/html/latest/filesystems/proc.html - char status[2048] = { 0 }; + char status[2048]; int fd = ::open("/proc/self/status", O_RDONLY); if (fd == -1) { @@ -471,6 +471,8 @@ namespace pal { // We have data. At this point we can likely make a strong decision. const char tracer_pid_name[] = "TracerPid:"; + // null terminate status + status[bytes_read] = '\0'; const char* tracer_pid_ptr = ::strstr(status, tracer_pid_name); if (tracer_pid_ptr == nullptr) return debugger_state_t::not_attached; 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/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..971d9ea575910 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. @@ -6335,39 +6333,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 +9209,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 2febde4d7365d..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); @@ -7064,8 +7066,6 @@ class Compiler void optCompactLoops(); void optCompactLoop(FlowGraphNaturalLoop* loop); - BasicBlock* optFindLoopCompactionInsertionPoint(FlowGraphNaturalLoop* loop, BasicBlock* top); - BasicBlock* optTryAdvanceLoopCompactionInsertionPoint(FlowGraphNaturalLoop* loop, BasicBlock* insertionPoint, BasicBlock* top, BasicBlock* bottom); bool optCreatePreheader(FlowGraphNaturalLoop* loop); void optSetWeightForPreheaderOrExit(FlowGraphNaturalLoop* loop, BasicBlock* block); @@ -8337,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/emit.cpp b/src/coreclr/jit/emit.cpp index f1f716d6de420..33ac26acfd106 100644 --- a/src/coreclr/jit/emit.cpp +++ b/src/coreclr/jit/emit.cpp @@ -6773,12 +6773,10 @@ unsigned emitter::emitEndCodeGen(Compiler* comp, #endif #if defined(TARGET_XARCH) || defined(TARGET_ARM64) - // For x64/x86/arm64, align methods that are "optimizations enabled" to 32 byte boundaries if - // they are larger than 16 bytes and contain a loop. + // For x64/x86/arm64, align methods that contain a loop to 32 byte boundaries if + // they are larger than 16 bytes and loop alignment is enabled. // - if (emitComp->opts.OptimizationEnabled() && - (!emitComp->opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT) || comp->IsTargetAbi(CORINFO_NATIVEAOT_ABI)) && - (emitTotalHotCodeSize > 16) && emitComp->fgHasLoops) + if (codeGen->ShouldAlignLoops() && (emitTotalHotCodeSize > 16) && emitComp->fgHasLoops) { codeAlignment = 32; } diff --git a/src/coreclr/jit/emitxarch.cpp b/src/coreclr/jit/emitxarch.cpp index 71cafb0d5f488..500d827ab29ca 100644 --- a/src/coreclr/jit/emitxarch.cpp +++ b/src/coreclr/jit/emitxarch.cpp @@ -2789,7 +2789,14 @@ bool emitter::emitInsCanOnlyWriteSSE2OrAVXReg(instrDesc* id) // These SSE instructions write to a general purpose integer register. return false; } - + case INS_kmovb_gpr: + case INS_kmovw_gpr: + case INS_kmovd_gpr: + case INS_kmovq_gpr: + { + // These kmov writes to a general purpose integer register + return !isGeneralRegister(id->idReg1()); + } default: { return true; 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/gentree.cpp b/src/coreclr/jit/gentree.cpp index c60bff8c10202..e021613381de5 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -20824,6 +20824,16 @@ GenTree* Compiler::gtNewSimdBinOpNode( if (op2->IsCnsIntOrI()) { op2->AsIntCon()->gtIconVal &= shiftCountMask; +#ifdef TARGET_ARM64 + // On ARM64, ShiftRight* intrinsics cannot encode a shift value of zero, + // so use the generic Shift* fallback intrinsic. + // GenTreeHWIntrinsic::GetHWIntrinsicIdForBinOp will see that the immediate node is not const, + // and return the correct fallback intrinsic. + if ((op != GT_LSH) && (op2->AsIntCon()->IconValue() == 0)) + { + op2 = gtNewZeroConNode(type); + } +#endif // TARGET_ARM64 } else { diff --git a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp index bd5027cd4e02d..d2a4bb4d2caf1 100644 --- a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp +++ b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp @@ -434,18 +434,8 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) for (helper.EmitBegin(); !helper.Done(); helper.EmitCaseEnd()) { const int shiftAmount = helper.ImmValue(); - - if (shiftAmount == 0) - { - // TODO: Use emitIns_Mov instead. - // We do not use it currently because it will still elide the 'mov' - // even if 'canSkip' is false. We cannot elide the 'mov' here. - GetEmitter()->emitIns_R_R_R(INS_mov, emitTypeSize(node), targetReg, reg, reg); - } - else - { - GetEmitter()->emitIns_R_R_I(ins, emitSize, targetReg, reg, shiftAmount, opt); - } + assert((shiftAmount != 0) || (intrin.category == HW_Category_ShiftLeftByImmediate)); + GetEmitter()->emitIns_R_R_I(ins, emitSize, targetReg, reg, shiftAmount, opt); } }; diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp index f8bc800241491..d92895a9d4980 100644 --- a/src/coreclr/jit/lower.cpp +++ b/src/coreclr/jit/lower.cpp @@ -8962,12 +8962,22 @@ void Lowering::LowerStoreIndirCoalescing(GenTreeIndir* ind) assert(prevData.IsStore()); assert(currData.IsStore()); - // For now, only constants are supported for data. + // For now, only non-relocatable constants are supported for data. if (!prevData.value->OperIsConst() || !currData.value->OperIsConst()) { return; } + if (prevData.value->IsCnsIntOrI() && prevData.value->AsIntCon()->ImmedValNeedsReloc(comp)) + { + return; + } + + if (currData.value->IsCnsIntOrI() && currData.value->AsIntCon()->ImmedValNeedsReloc(comp)) + { + return; + } + // Otherwise, the difference between two offsets has to match the size of the type. // We don't support overlapping stores. if (abs(prevData.offset - currData.offset) != (int)genTypeSize(prevData.targetType)) diff --git a/src/coreclr/jit/optimizer.cpp b/src/coreclr/jit/optimizer.cpp index 1a9d2bc466407..f9880026eab26 100644 --- a/src/coreclr/jit/optimizer.cpp +++ b/src/coreclr/jit/optimizer.cpp @@ -2828,7 +2828,7 @@ void Compiler::optCompactLoop(FlowGraphNaturalLoop* loop) if (insertionPoint == nullptr) { - insertionPoint = optFindLoopCompactionInsertionPoint(loop, top); + insertionPoint = loop->GetLexicallyBottomMostBlock(); } BasicBlock* previous = cur->Prev(); @@ -2842,8 +2842,6 @@ void Compiler::optCompactLoop(FlowGraphNaturalLoop* loop) } // Now physically move the blocks. - BasicBlock* moveBefore = insertionPoint->Next(); - fgUnlinkRange(cur, lastNonLoopBlock); fgMoveBlocksAfter(cur, lastNonLoopBlock, insertionPoint); ehUpdateLastBlocks(insertionPoint, lastNonLoopBlock); @@ -2855,137 +2853,6 @@ void Compiler::optCompactLoop(FlowGraphNaturalLoop* loop) } } -//----------------------------------------------------------------------------- -// optFindLoopCompactionInsertionPoint: Find a good insertion point at which to -// move blocks from the lexical range of "loop" that is not part of the loop. -// -// Parameters: -// loop - The loop -// top - Lexical top block of the loop. -// -// Returns: -// Non-null insertion point. -// -BasicBlock* Compiler::optFindLoopCompactionInsertionPoint(FlowGraphNaturalLoop* loop, BasicBlock* top) -{ - // Find an insertion point for blocks we're going to move. Move them down - // out of the loop, and if possible find a spot that won't break up fall-through. - BasicBlock* bottom = loop->GetLexicallyBottomMostBlock(); - BasicBlock* insertionPoint = bottom; - while (!insertionPoint->IsLast()) - { - switch (insertionPoint->GetKind()) - { - case BBJ_ALWAYS: - if (!insertionPoint->JumpsToNext()) - { - // Found a branch that isn't to the next block, so we won't split up any fall-through. - return insertionPoint; - } - break; - - case BBJ_COND: - if (!insertionPoint->FalseTargetIs(insertionPoint->Next())) - { - // Found a conditional branch that doesn't have a false branch to the next block, - // so we won't split up any fall-through. - return insertionPoint; - } - break; - - case BBJ_CALLFINALLY: - if (!insertionPoint->isBBCallFinallyPair()) - { - // Found a retless BBJ_CALLFINALLY block, so we won't split up any fall-through. - return insertionPoint; - } - break; - - default: - // No fall-through to split up. - return insertionPoint; - } - - // Keep looking for a better insertion point if we can. - BasicBlock* newInsertionPoint = optTryAdvanceLoopCompactionInsertionPoint(loop, insertionPoint, top, bottom); - if (newInsertionPoint == nullptr) - { - // Ran out of candidate insertion points, so just split up the fall-through. - break; - } - - insertionPoint = newInsertionPoint; - } - - return insertionPoint; -} - -//----------------------------------------------------------------------------- -// optTryAdvanceLoopCompactionInsertionPoint: Advance the insertion point to -// avoid having to insert new blocks due to fallthrough. -// -// Parameters: -// loop - The loop -// insertionPoint - Current insertion point -// top - Lexical top block of the loop. -// bottom - Lexical bottom block of the loop. -// -// Returns: -// New insertion point. -// -BasicBlock* Compiler::optTryAdvanceLoopCompactionInsertionPoint(FlowGraphNaturalLoop* loop, - BasicBlock* insertionPoint, - BasicBlock* top, - BasicBlock* bottom) -{ - BasicBlock* newInsertionPoint = insertionPoint->Next(); - - if (!BasicBlock::sameEHRegion(insertionPoint, newInsertionPoint)) - { - // Don't cross an EH region boundary. - return nullptr; - } - - // TODO-Quirk: Compatibility with old compaction - if (newInsertionPoint->KindIs(BBJ_ALWAYS, BBJ_COND)) - { - BasicBlock* dest = - newInsertionPoint->KindIs(BBJ_ALWAYS) ? newInsertionPoint->GetTarget() : newInsertionPoint->GetTrueTarget(); - if ((dest->bbNum >= top->bbNum) && (dest->bbNum <= bottom->bbNum) && !loop->ContainsBlock(dest)) - { - return nullptr; - } - } - - // TODO-Quirk: Compatibility with old compaction - for (BasicBlock* const predBlock : newInsertionPoint->PredBlocks()) - { - if ((predBlock->bbNum >= top->bbNum) && (predBlock->bbNum <= bottom->bbNum) && !loop->ContainsBlock(predBlock)) - { - // Don't make this forward edge a backwards edge. - return nullptr; - } - } - - // Compaction runs on outer loops before inner loops. That means all - // unlexical blocks here are part of an ancestor loop (or trivial - // BBJ_ALWAYS exit blocks). To avoid breaking lexicality of ancestor loops - // we avoid moving any block past the bottom of an ancestor loop. - for (FlowGraphNaturalLoop* ancestor = loop->GetParent(); ancestor != nullptr; ancestor = ancestor->GetParent()) - { - if (newInsertionPoint == ancestor->GetLexicallyBottomMostBlock()) - { - return nullptr; - } - } - - // Advancing the insertion point is ok, except that we can't split up any call finally - // pair, so if we've got such a pair recurse to see if we can move past the whole thing. - return newInsertionPoint->isBBCallFinallyPair() - ? optTryAdvanceLoopCompactionInsertionPoint(loop, newInsertionPoint, top, bottom) - : newInsertionPoint; -} - //----------------------------------------------------------------------------- // optCreatePreheader: Create (or find) a preheader for a natural loop. // @@ -3024,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()); @@ -3136,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/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 cd03be337899b..4478a450df9d5 100644 --- a/src/coreclr/vm/appdomain.cpp +++ b/src/coreclr/vm/appdomain.cpp @@ -430,27 +430,6 @@ void PinnedHeapHandleTable::EnumStaticGCRefs(promote_func* fn, ScanContext* sc) } } -//***************************************************************************** -// BaseDomain -//***************************************************************************** - -BaseDomain::BaseDomain() -{ - // initialize fields so the domain can be safely destructed - // shouldn't call anything that can fail here - use ::Init instead - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - FORBID_FAULT; - } - CONTRACTL_END; - - // Make sure the container is set to NULL so that it gets loaded when it is used. - m_pPinnedHeapHandleTable = NULL; -} //BaseDomain::BaseDomain - #undef LOADERHEAP_PROFILE_COUNTER void AppDomain::ClearBinderContext() @@ -573,7 +552,7 @@ void AppDomain::SetNativeDllSearchDirectories(LPCWSTR wszNativeDllSearchDirector } } -OBJECTREF* BaseDomain::AllocateObjRefPtrsInLargeTable(int nRequested, DynamicStaticsInfo* pStaticsInfo, MethodTable *pMTToFillWithStaticBoxes, bool isClassInitdeByUpdatingStaticPointer) +OBJECTREF* AppDomain::AllocateObjRefPtrsInLargeTable(int nRequested, DynamicStaticsInfo* pStaticsInfo, MethodTable *pMTToFillWithStaticBoxes, bool isClassInitdeByUpdatingStaticPointer) { CONTRACTL { @@ -661,7 +640,7 @@ OBJECTREF AppDomain::GetMissingObject() #ifndef DACCESS_COMPILE -STRINGREF *BaseDomain::IsStringInterned(STRINGREF *pString) +STRINGREF* AppDomain::IsStringInterned(STRINGREF *pString) { CONTRACTL { @@ -676,7 +655,7 @@ STRINGREF *BaseDomain::IsStringInterned(STRINGREF *pString) return GetLoaderAllocator()->IsStringInterned(pString); } -STRINGREF *BaseDomain::GetOrInternString(STRINGREF *pString) +STRINGREF* AppDomain::GetOrInternString(STRINGREF *pString) { CONTRACTL { @@ -691,7 +670,7 @@ STRINGREF *BaseDomain::GetOrInternString(STRINGREF *pString) return GetLoaderAllocator()->GetOrInternString(pString); } -void BaseDomain::InitPinnedHeapHandleTable() +void AppDomain::InitPinnedHeapHandleTable() { CONTRACTL { @@ -1622,6 +1601,30 @@ HRESULT SystemDomain::NotifyProfilerShutdown() #endif // PROFILING_SUPPORTED AppDomain::AppDomain() + : m_handleStore{NULL} + , m_pPinnedHeapHandleTable{NULL} + , m_pDefaultBinder{NULL} + , m_pRefClassFactHash{NULL} +#ifdef FEATURE_COMINTEROP + , m_pRefDispIDCache{NULL} + , m_hndMissing{NULL} +#endif //FEATURE_COMINTEROP + , m_pDelayedLoaderAllocatorUnloadList{NULL} + , m_pRootAssembly{NULL} + , m_dwFlags{0} + , m_cRef{1} +#ifdef FEATURE_COMINTEROP + , m_pRCWCache{NULL} +#endif //FEATURE_COMINTEROP +#ifdef FEATURE_COMWRAPPERS + , m_pRCWRefCache{NULL} +#endif // FEATURE_COMWRAPPERS + , m_Stage{STAGE_CREATING} + , m_MemoryPressure{0} + , m_ForceTrivialWaitOperations{false} +#ifdef FEATURE_TYPEEQUIVALENCE + , m_pTypeEquivalenceTable{NULL} +#endif // FEATURE_TYPEEQUIVALENCE { // initialize fields so the appdomain can be safely destructed // shouldn't call anything that can fail here - use ::Init instead @@ -1634,45 +1637,16 @@ AppDomain::AppDomain() } CONTRACTL_END; - m_cRef=1; - m_JITLock.PreInit(); m_ClassInitLock.PreInit(); m_ILStubGenLock.PreInit(); m_NativeTypeLoadLock.PreInit(); m_FileLoadLock.PreInit(); - m_pDefaultBinder = NULL; - m_pRootAssembly = NULL; - - m_dwFlags = 0; -#ifdef FEATURE_COMINTEROP - m_pRCWCache = NULL; -#endif //FEATURE_COMINTEROP -#ifdef FEATURE_COMWRAPPERS - m_pRCWRefCache = NULL; -#endif // FEATURE_COMWRAPPERS - - m_handleStore = NULL; - #ifdef _DEBUG m_Assemblies.Debug_SetAppDomain(this); #endif // _DEBUG -#ifdef FEATURE_COMINTEROP - m_pRefDispIDCache = NULL; - m_hndMissing = NULL; -#endif - - m_pRefClassFactHash = NULL; - - m_ForceTrivialWaitOperations = false; - m_Stage=STAGE_CREATING; - -#ifdef FEATURE_TYPEEQUIVALENCE - m_pTypeEquivalenceTable = NULL; -#endif // FEATURE_TYPEEQUIVALENCE - } // AppDomain::AppDomain AppDomain::~AppDomain() @@ -1696,13 +1670,10 @@ void AppDomain::Init() CONTRACTL { STANDARD_VM_CHECK; + PRECONDITION(m_Stage == STAGE_CREATING); } CONTRACTL_END; - m_pDelayedLoaderAllocatorUnloadList = NULL; - - SetStage( STAGE_CREATING); - // // The JIT lock and the CCtor locks are at the same level (and marked as // UNSAFE_SAME_LEVEL) because they are all part of the same deadlock detection mechanism. We @@ -1729,8 +1700,6 @@ void AppDomain::Init() // Set up the binding caches m_AssemblyCache.Init(&m_DomainCacheCrst, GetHighFrequencyHeap()); - m_MemoryPressure = 0; - m_handleStore = GCHandleUtilities::GetGCHandleManager()->GetGlobalHandleStore(); if (!m_handleStore) { @@ -2512,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 @@ -2547,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) @@ -4057,7 +4031,7 @@ void AppDomain::EnumStaticGCRefs(promote_func* fn, ScanContext* sc) #endif // !DACCESS_COMPILE //------------------------------------------------------------------------ -PTR_LoaderAllocator BaseDomain::GetLoaderAllocator() +PTR_LoaderAllocator AppDomain::GetLoaderAllocator() { WRAPPER_NO_CONTRACT; return SystemDomain::GetGlobalLoaderAllocator(); // The one and only domain is not unloadable @@ -4536,7 +4510,7 @@ SystemDomain::EnumMemoryRegions(CLRDataEnumMemoryFlags flags, bool enumThis) if (flags == CLRDATA_ENUM_MEM_HEAP2) { - GetLoaderAllocator()->EnumMemoryRegions(flags); + GetGlobalLoaderAllocator()->EnumMemoryRegions(flags); } if (m_pSystemPEAssembly.IsValid()) { diff --git a/src/coreclr/vm/appdomain.hpp b/src/coreclr/vm/appdomain.hpp index b2fcc9d58696c..ef026a3704de7 100644 --- a/src/coreclr/vm/appdomain.hpp +++ b/src/coreclr/vm/appdomain.hpp @@ -457,12 +457,11 @@ class BaseDomain // // Initialization/shutdown routines for every instance of an BaseDomain. - BaseDomain(); + BaseDomain() = default; virtual ~BaseDomain() {} virtual BOOL IsAppDomain() { LIMITED_METHOD_DAC_CONTRACT; return FALSE; } - PTR_LoaderAllocator GetLoaderAllocator(); virtual PTR_AppDomain AsAppDomain() { LIMITED_METHOD_CONTRACT; @@ -470,24 +469,6 @@ class BaseDomain return NULL; } - STRINGREF *IsStringInterned(STRINGREF *pString); - STRINGREF *GetOrInternString(STRINGREF *pString); - - // Returns an array of OBJECTREF* that can be used to store domain specific data. - // Statics and reflection info (Types, MemberInfo,..) are stored this way - // If pStaticsInfo != 0, allocation will only take place if GC statics in the DynamicStaticsInfo are NULL (and the allocation - // will be properly serialized) - OBJECTREF *AllocateObjRefPtrsInLargeTable(int nRequested, DynamicStaticsInfo* pStaticsInfo = NULL, MethodTable *pMTToFillWithStaticBoxes = NULL, bool isClassInitdeByUpdatingStaticPointer = false); - -protected: - - //**************************************************************************************** - // Helper method to initialize the large heap handle table. - void InitPinnedHeapHandleTable(); - - // The pinned heap handle table. - PinnedHeapHandleTable *m_pPinnedHeapHandleTable; - #ifdef DACCESS_COMPILE public: virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags, bool enumThis) = 0; @@ -752,6 +733,11 @@ class AppDomain : public BaseDomain virtual BOOL IsAppDomain() { LIMITED_METHOD_DAC_CONTRACT; return TRUE; } virtual PTR_AppDomain AsAppDomain() { LIMITED_METHOD_CONTRACT; return dac_cast(this); } + PTR_LoaderAllocator GetLoaderAllocator(); + + STRINGREF *IsStringInterned(STRINGREF *pString); + STRINGREF *GetOrInternString(STRINGREF *pString); + OBJECTREF GetRawExposedObject() { LIMITED_METHOD_CONTRACT; return NULL; } OBJECTHANDLE GetRawExposedObjectHandleForDebugger() { LIMITED_METHOD_DAC_CONTRACT; return (OBJECTHANDLE)NULL; } @@ -1256,6 +1242,12 @@ class AppDomain : public BaseDomain void NotifyDebuggerUnload(); #endif // DEBUGGING_SUPPORTED +public: + // Returns an array of OBJECTREF* that can be used to store domain specific data. + // Statics and reflection info (Types, MemberInfo,..) are stored this way + // If pStaticsInfo != 0, allocation will only take place if GC statics in the DynamicStaticsInfo are NULL (and the allocation + // will be properly serialized) + OBJECTREF *AllocateObjRefPtrsInLargeTable(int nRequested, DynamicStaticsInfo* pStaticsInfo = NULL, MethodTable *pMTToFillWithStaticBoxes = NULL, bool isClassInitdeByUpdatingStaticPointer = false); #ifndef DACCESS_COMPILE OBJECTREF* AllocateStaticFieldObjRefPtrs(int nRequested) { @@ -1265,7 +1257,16 @@ class AppDomain : public BaseDomain } #endif // DACCESS_COMPILE - void EnumStaticGCRefs(promote_func* fn, ScanContext* sc); +private: + // Helper method to initialize the large heap handle table. + void InitPinnedHeapHandleTable(); + +private: + // The pinned heap handle table. + PinnedHeapHandleTable *m_pPinnedHeapHandleTable; + +public: + void EnumStaticGCRefs(promote_func* fn, ScanContext* sc); void SetupSharedStatics(); @@ -2013,7 +2014,7 @@ class SystemDomain : public BaseDomain m_pDelayedUnloadListOfLoaderAllocators=NULL; - m_GlobalAllocator.Init(this); + m_GlobalAllocator.Init(); } #endif @@ -2022,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 7d9b823137045..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; } @@ -639,11 +640,9 @@ Module *Assembly::FindModuleByExportedType(mdExportedType mdType, { #ifndef DACCESS_COMPILE // LoadAssembly never returns NULL - DomainAssembly * pDomainAssembly = - GetModule()->LoadAssembly(mdLinkRef); - PREFIX_ASSUME(pDomainAssembly != NULL); - - RETURN pDomainAssembly->GetModule(); + pAssembly = GetModule()->LoadAssembly(mdLinkRef); + PREFIX_ASSUME(pAssembly != NULL); + break; #else _ASSERTE(!"DAC shouldn't attempt to trigger loading"); return NULL; @@ -868,14 +867,7 @@ Module * Assembly::FindModuleByTypeRef( RETURN NULL; } - - DomainAssembly * pDomainAssembly = pModule->LoadAssembly(tkType); - - - if (pDomainAssembly == NULL) - RETURN NULL; - - pAssembly = pDomainAssembly->GetAssembly(); + pAssembly = pModule->LoadAssembly(tkType); if (pAssembly == NULL) { RETURN NULL; diff --git a/src/coreclr/vm/assemblynative.cpp b/src/coreclr/vm/assemblynative.cpp index 94220a1e35bad..02ba71a51c323 100644 --- a/src/coreclr/vm/assemblynative.cpp +++ b/src/coreclr/vm/assemblynative.cpp @@ -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/assemblyspec.cpp b/src/coreclr/vm/assemblyspec.cpp index 11a394f665c46..685aa71675762 100644 --- a/src/coreclr/vm/assemblyspec.cpp +++ b/src/coreclr/vm/assemblyspec.cpp @@ -295,24 +295,6 @@ void AssemblySpec::InitializeAssemblyNameRef(_In_ BINDER_SPACE::AssemblyName* as spec.AssemblyNameInit(assemblyNameRef); } -Assembly *AssemblySpec::LoadAssembly(FileLoadLevel targetLevel, BOOL fThrowOnFileNotFound) -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - } - CONTRACTL_END; - - DomainAssembly * pDomainAssembly = LoadDomainAssembly(targetLevel, fThrowOnFileNotFound); - if (pDomainAssembly == NULL) { - _ASSERTE(!fThrowOnFileNotFound); - return NULL; - } - return pDomainAssembly->GetAssembly(); -} - AssemblyBinder* AssemblySpec::GetBinderFromParentAssembly(AppDomain *pDomain) { CONTRACTL @@ -372,10 +354,10 @@ AssemblyBinder* AssemblySpec::GetBinderFromParentAssembly(AppDomain *pDomain) return pParentAssemblyBinder; } -DomainAssembly *AssemblySpec::LoadDomainAssembly(FileLoadLevel targetLevel, - BOOL fThrowOnFileNotFound) +Assembly *AssemblySpec::LoadAssembly(FileLoadLevel targetLevel, + BOOL fThrowOnFileNotFound) { - CONTRACT(DomainAssembly *) + CONTRACT(Assembly *) { INSTANCE_CHECK; THROWS; @@ -390,23 +372,21 @@ DomainAssembly *AssemblySpec::LoadDomainAssembly(FileLoadLevel targetLevel, ETWOnStartup (LoaderCatchCall_V1, LoaderCatchCallEnd_V1); AppDomain* pDomain = GetAppDomain(); - DomainAssembly* pAssembly = pDomain->FindCachedAssembly(this); - if (pAssembly) + DomainAssembly* domainAssembly = pDomain->FindCachedAssembly(this); + if (domainAssembly) { BinderTracing::AssemblyBindOperation bindOperation(this); - bindOperation.SetResult(pAssembly->GetPEAssembly(), true /*cached*/); + bindOperation.SetResult(domainAssembly->GetPEAssembly(), true /*cached*/); - pDomain->LoadDomainAssembly(pAssembly, targetLevel); - RETURN pAssembly; + pDomain->LoadDomainAssembly(domainAssembly, targetLevel); + RETURN domainAssembly->GetAssembly(); } PEAssemblyHolder pFile(pDomain->BindAssemblySpec(this, fThrowOnFileNotFound)); if (pFile == NULL) RETURN NULL; - pAssembly = pDomain->LoadDomainAssembly(this, pFile, targetLevel); - - RETURN pAssembly; + RETURN pDomain->LoadAssembly(this, pFile, targetLevel); } /* static */ diff --git a/src/coreclr/vm/assemblyspec.hpp b/src/coreclr/vm/assemblyspec.hpp index 96b8e409d1d99..ba55c75fa12c4 100644 --- a/src/coreclr/vm/assemblyspec.hpp +++ b/src/coreclr/vm/assemblyspec.hpp @@ -45,7 +45,6 @@ class AssemblySpec : public BaseAssemblySpec friend Assembly * Module::GetAssemblyIfLoaded( mdAssemblyRef kAssemblyRef, IMDInternalImport * pMDImportOverride, - BOOL fDoNotUtilizeExtraChecks, AssemblyBinder *pBinderForLoadedAssembly); public: @@ -175,8 +174,6 @@ class AssemblySpec : public BaseAssemblySpec Assembly *LoadAssembly(FileLoadLevel targetLevel, BOOL fThrowOnFileNotFound = TRUE); - DomainAssembly *LoadDomainAssembly(FileLoadLevel targetLevel, - BOOL fThrowOnFileNotFound = TRUE); public: // static // Creates and loads an assembly based on the name and context. diff --git a/src/coreclr/vm/ceeload.cpp b/src/coreclr/vm/ceeload.cpp index 9b72e47d2e1bf..4d585435d6440 100644 --- a/src/coreclr/vm/ceeload.cpp +++ b/src/coreclr/vm/ceeload.cpp @@ -2258,7 +2258,6 @@ Assembly * Module::GetAssemblyIfLoaded( mdAssemblyRef kAssemblyRef, IMDInternalImport * pMDImportOverride, // = NULL - BOOL fDoNotUtilizeExtraChecks, // = FALSE AssemblyBinder *pBinderForLoadedAssembly // = NULL ) { @@ -2387,9 +2386,9 @@ ModuleBase::GetAssemblyRefFlags( } // Module::GetAssemblyRefFlags #ifndef DACCESS_COMPILE -DomainAssembly * Module::LoadAssemblyImpl(mdAssemblyRef kAssemblyRef) +Assembly * Module::LoadAssemblyImpl(mdAssemblyRef kAssemblyRef) { - CONTRACT(DomainAssembly *) + CONTRACT(Assembly *) { INSTANCE_CHECK; if (FORBIDGC_LOADER_USE_ENABLED()) NOTHROW; else THROWS; @@ -2402,20 +2401,17 @@ DomainAssembly * Module::LoadAssemblyImpl(mdAssemblyRef kAssemblyRef) ETWOnStartup (LoaderCatchCall_V1, LoaderCatchCallEnd_V1); - DomainAssembly * pDomainAssembly; - // // Early out quickly if the result is cached // Assembly * pAssembly = LookupAssemblyRef(kAssemblyRef); if (pAssembly != NULL) { - pDomainAssembly = pAssembly->GetDomainAssembly(); - ::GetAppDomain()->LoadDomainAssembly(pDomainAssembly, FILE_LOADED); - - RETURN pDomainAssembly; + ::GetAppDomain()->LoadDomainAssembly(pAssembly->GetDomainAssembly(), FILE_LOADED); + RETURN pAssembly; } + DomainAssembly * pDomainAssembly; { PEAssemblyHolder pPEAssembly = GetPEAssembly()->LoadAssembly(kAssemblyRef); AssemblySpec spec; @@ -2431,23 +2427,18 @@ DomainAssembly * Module::LoadAssemblyImpl(mdAssemblyRef kAssemblyRef) pDomainAssembly = GetAppDomain()->LoadDomainAssembly(&spec, pPEAssembly, FILE_LOADED); } - if (pDomainAssembly != NULL) - { - _ASSERTE( - pDomainAssembly->IsSystem() || // GetAssemblyIfLoaded will not find CoreLib (see AppDomain::FindCachedFile) - !pDomainAssembly->IsLoaded() || // GetAssemblyIfLoaded will not find not-yet-loaded assemblies - GetAssemblyIfLoaded(kAssemblyRef, NULL, FALSE, pDomainAssembly->GetPEAssembly()->GetHostAssembly()->GetBinder()) != NULL); // GetAssemblyIfLoaded should find all remaining cases + pAssembly = pDomainAssembly->GetAssembly(); + _ASSERTE(pDomainAssembly->IsLoaded() && pAssembly != NULL); + _ASSERTE( + pDomainAssembly->IsSystem() || // GetAssemblyIfLoaded will not find CoreLib (see AppDomain::FindCachedFile) + GetAssemblyIfLoaded(kAssemblyRef, NULL, pDomainAssembly->GetPEAssembly()->GetHostAssembly()->GetBinder()) != NULL); // GetAssemblyIfLoaded should find all remaining cases - if (pDomainAssembly->GetAssembly() != NULL) - { - StoreAssemblyRef(kAssemblyRef, pDomainAssembly->GetAssembly()); - } - } + StoreAssemblyRef(kAssemblyRef, pAssembly); - RETURN pDomainAssembly; + RETURN pAssembly; } #else -DomainAssembly * Module::LoadAssemblyImpl(mdAssemblyRef kAssemblyRef) +Assembly * Module::LoadAssemblyImpl(mdAssemblyRef kAssemblyRef) { WRAPPER_NO_CONTRACT; ThrowHR(E_FAIL); diff --git a/src/coreclr/vm/ceeload.h b/src/coreclr/vm/ceeload.h index 5892dc1a075ed..decc73bb336f9 100644 --- a/src/coreclr/vm/ceeload.h +++ b/src/coreclr/vm/ceeload.h @@ -466,7 +466,7 @@ class ModuleBase // The vtable needs to match between DAC and non-DAC, but we don't want any use of IsSigInIL in the DAC virtual BOOL IsSigInILImpl(PCCOR_SIGNATURE signature) { return FALSE; } // ModuleBase doesn't have a PE image to examine // The vtable needs to match between DAC and non-DAC, but we don't want any use of LoadAssembly in the DAC - virtual DomainAssembly * LoadAssemblyImpl(mdAssemblyRef kAssemblyRef) = 0; + virtual Assembly * LoadAssemblyImpl(mdAssemblyRef kAssemblyRef) = 0; // The vtable needs to match between DAC and non-DAC, but we don't want any use of ThrowTypeLoadException in the DAC virtual void DECLSPEC_NORETURN ThrowTypeLoadExceptionImpl(IMDInternalImport *pInternalImport, @@ -552,7 +552,6 @@ class ModuleBase virtual Assembly * GetAssemblyIfLoaded( mdAssemblyRef kAssemblyRef, IMDInternalImport * pMDImportOverride = NULL, - BOOL fDoNotUtilizeExtraChecks = FALSE, AssemblyBinder *pBinderForLoadedAssembly = NULL ) { @@ -573,7 +572,7 @@ class ModuleBase // The vtable needs to match between DAC and non-DAC, but we don't want any use of IsSigInIL in the DAC BOOL IsSigInIL(PCCOR_SIGNATURE signature) { return IsSigInILImpl(signature); } - DomainAssembly * LoadAssembly(mdAssemblyRef kAssemblyRef) + Assembly * LoadAssembly(mdAssemblyRef kAssemblyRef) { WRAPPER_NO_CONTRACT; return LoadAssemblyImpl(kAssemblyRef); @@ -1129,7 +1128,6 @@ class Module : public ModuleBase Assembly * GetAssemblyIfLoaded( mdAssemblyRef kAssemblyRef, IMDInternalImport * pMDImportOverride = NULL, - BOOL fDoNotUtilizeExtraChecks = FALSE, AssemblyBinder *pBinderForLoadedAssembly = NULL ) final; @@ -1140,7 +1138,7 @@ class Module : public ModuleBase UINT resIDWhy) final; #endif - DomainAssembly * LoadAssemblyImpl(mdAssemblyRef kAssemblyRef) final; + Assembly * LoadAssemblyImpl(mdAssemblyRef kAssemblyRef) final; public: PTR_Module LookupModule(mdToken kFile) final; Module *GetModuleIfLoaded(mdFile kFile) final; 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 23dfb4d238803..73cc949ec66d5 100644 --- a/src/coreclr/vm/comsynchronizable.cpp +++ b/src/coreclr/vm/comsynchronizable.cpp @@ -69,37 +69,28 @@ static INT32 MapToNTPriority(INT32 ours) } CONTRACTL_END; - INT32 NTPriority = 0; - switch (ours) { case ThreadNative::PRIORITY_LOWEST: - NTPriority = THREAD_PRIORITY_LOWEST; - break; + return THREAD_PRIORITY_LOWEST; case ThreadNative::PRIORITY_BELOW_NORMAL: - NTPriority = THREAD_PRIORITY_BELOW_NORMAL; - break; + return THREAD_PRIORITY_BELOW_NORMAL; case ThreadNative::PRIORITY_NORMAL: - NTPriority = THREAD_PRIORITY_NORMAL; - break; + return THREAD_PRIORITY_NORMAL; case ThreadNative::PRIORITY_ABOVE_NORMAL: - NTPriority = THREAD_PRIORITY_ABOVE_NORMAL; - break; + return THREAD_PRIORITY_ABOVE_NORMAL; case ThreadNative::PRIORITY_HIGHEST: - NTPriority = THREAD_PRIORITY_HIGHEST; - break; + return THREAD_PRIORITY_HIGHEST; default: COMPlusThrow(kArgumentOutOfRangeException, W("Argument_InvalidFlag")); } - return NTPriority; } - // Map to our exposed notion of thread priorities from the enumeration that NT uses. INT32 MapFromNTPriority(INT32 NTPriority) { @@ -252,6 +243,8 @@ extern "C" void QCALLTYPE ThreadNative_Start(QCall::ThreadHandle thread, int thr void ThreadNative::Start(Thread* pNewThread, int threadStackSize, int priority, PCWSTR pThreadName) { + STANDARD_VM_CONTRACT; + _ASSERTE(pNewThread != NULL); // Is the thread already started? You can't restart a thread. @@ -292,7 +285,9 @@ void ThreadNative::Start(Thread* pNewThread, int threadStackSize, int priority, // After we have established the thread handle, we can check m_Priority. // This ordering is required to eliminate the race condition on setting the // priority of a thread just as it starts up. - pNewThread->SetThreadPriority(MapToNTPriority(priority)); + INT32 NTPriority = MapToNTPriority(priority); + + pNewThread->SetThreadPriority(NTPriority); pNewThread->ChooseThreadCPUGroupAffinity(); pNewThread->SetThreadState(Thread::TS_LegalToJoin); @@ -326,65 +321,46 @@ void ThreadNative::Start(Thread* pNewThread, int threadStackSize, int priority, } } -// Note that you can manipulate the priority of a thread that hasn't started yet, -// or one that is running. But you get an exception if you manipulate the priority -// of a thread that has died. -FCIMPL1(INT32, ThreadNative::GetPriority, ThreadBaseObject* pThisUNSAFE) +extern "C" void QCALLTYPE ThreadNative_SetPriority(QCall::ObjectHandleOnStack thread, INT32 iPriority) { - FCALL_CONTRACT; - - if (pThisUNSAFE==NULL) - FCThrowRes(kNullReferenceException, W("NullReference_This")); - - // validate the handle - if (ThreadIsDead(pThisUNSAFE->GetInternal())) - FCThrowRes(kThreadStateException, W("ThreadState_Dead_Priority")); - - return pThisUNSAFE->m_Priority; -} -FCIMPLEND + QCALL_CONTRACT; -FCIMPL2(void, ThreadNative::SetPriority, ThreadBaseObject* pThisUNSAFE, INT32 iPriority) -{ - FCALL_CONTRACT; + BEGIN_QCALL; - int priority; - Thread *thread; + GCX_COOP(); - THREADBASEREF pThis = (THREADBASEREF) pThisUNSAFE; - HELPER_METHOD_FRAME_BEGIN_1(pThis); + THREADBASEREF threadRef = NULL; + GCPROTECT_BEGIN(threadRef) + threadRef = (THREADBASEREF)thread.Get(); - if (pThis==NULL) - { + if (threadRef == NULL) COMPlusThrow(kNullReferenceException, W("NullReference_This")); - } - - // translate the priority (validating as well) - priority = MapToNTPriority(iPriority); // can throw; needs a frame - // validate the thread - thread = pThis->GetInternal(); - - if (ThreadIsDead(thread)) - { + // Note that you can manipulate the priority of a thread that hasn't started yet, + // or one that is running. But you get an exception if you manipulate the priority + // of a thread that has died. + Thread* th = threadRef->GetInternal(); + if (ThreadIsDead(th)) COMPlusThrow(kThreadStateException, W("ThreadState_Dead_Priority")); - } - INT32 oldPriority = pThis->m_Priority; + // translate the priority (validating as well) + INT32 priority = MapToNTPriority(iPriority); + + INT32 oldPriority = threadRef->GetPriority(); - // Eliminate the race condition by establishing m_Priority before we check for if - // the thread is running. See ThreadNative::Start() for the other half. - pThis->m_Priority = iPriority; + // Eliminate the race condition by setting priority field before we check for if + // the thread is running. See ThreadNative::Start() for the other half. + threadRef->SetPriority(iPriority); - if (!thread->SetThreadPriority(priority)) + if (!th->SetThreadPriority(priority)) { - pThis->m_Priority = oldPriority; + threadRef->SetPriority(oldPriority); COMPlusThrow(kThreadStateException, W("ThreadState_SetPriorityFailed")); } - HELPER_METHOD_FRAME_END(); + GCPROTECT_END(); + END_QCALL; } -FCIMPLEND FCIMPL1(FC_BOOL_RET, ThreadNative::IsAlive, ThreadBaseObject* pThisUNSAFE) { @@ -417,30 +393,6 @@ FCIMPL1(FC_BOOL_RET, ThreadNative::IsAlive, ThreadBaseObject* pThisUNSAFE) } FCIMPLEND -FCIMPL2(FC_BOOL_RET, ThreadNative::Join, ThreadBaseObject* pThisUNSAFE, INT32 Timeout) -{ - FCALL_CONTRACT; - - BOOL retVal = FALSE; - THREADBASEREF pThis = (THREADBASEREF) pThisUNSAFE; - - HELPER_METHOD_FRAME_BEGIN_RET_1(pThis); - - if (pThis==NULL) - COMPlusThrow(kNullReferenceException, W("NullReference_This")); - - // validate the timeout - if ((Timeout < 0) && (Timeout != INFINITE_TIMEOUT)) - COMPlusThrowArgumentOutOfRange(W("millisecondsTimeout"), W("ArgumentOutOfRange_NeedNonNegOrNegative1")); - - retVal = DoJoin(pThis, Timeout); - - HELPER_METHOD_FRAME_END(); - - FC_RETURN_BOOL(retVal); -} -FCIMPLEND - NOINLINE static Object* GetCurrentThreadHelper() { FCALL_CONTRACT; @@ -591,83 +543,27 @@ FCIMPLEND #ifdef FEATURE_COMINTEROP_APARTMENT_SUPPORT -// Indicate whether the thread will host an STA (this may fail if the thread has -// already been made part of the MTA, use GetApartmentState or the return state -// from this routine to check for this). -FCIMPL2(INT32, ThreadNative::SetApartmentState, ThreadBaseObject* pThisUNSAFE, INT32 iState) -{ - FCALL_CONTRACT; - - if (pThisUNSAFE==NULL) - FCThrowRes(kNullReferenceException, W("NullReference_This")); - - BOOL ok = TRUE; - THREADBASEREF pThis = (THREADBASEREF) pThisUNSAFE; - - HELPER_METHOD_FRAME_BEGIN_RET_1(pThis); - - Thread *thread = pThis->GetInternal(); - if (!thread) - COMPlusThrow(kThreadStateException, IDS_EE_THREAD_CANNOT_GET); - - { - pThis->EnterObjMonitor(); - - // We can only change the apartment if the thread is unstarted or - // running, and if it's running we have to be in the thread's - // context. - if ((!ThreadNotStarted(thread) && !ThreadIsRunning(thread)) || - (!ThreadNotStarted(thread) && (GetThread() != thread))) - ok = FALSE; - else - { - EX_TRY - { - iState = thread->SetApartment((Thread::ApartmentState)iState); - } - EX_CATCH - { - pThis->LeaveObjMonitor(); - EX_RETHROW; - } - EX_END_CATCH_UNREACHABLE; - } - - pThis->LeaveObjMonitor(); - } - - // Now it's safe to throw exceptions again. - if (!ok) - COMPlusThrow(kThreadStateException); - - HELPER_METHOD_FRAME_END(); - - return iState; -} -FCIMPLEND - // Return whether the thread hosts an STA, is a member of the MTA or is not // currently initialized for COM. -FCIMPL1(INT32, ThreadNative::GetApartmentState, ThreadBaseObject* pThisUNSAFE) +extern "C" INT32 QCALLTYPE ThreadNative_GetApartmentState(QCall::ObjectHandleOnStack t) { - FCALL_CONTRACT; + QCALL_CONTRACT; INT32 retVal = 0; - THREADBASEREF refThis = (THREADBASEREF) ObjectToOBJECTREF(pThisUNSAFE); - - HELPER_METHOD_FRAME_BEGIN_RET_1(refThis); + BEGIN_QCALL; - if (refThis == NULL) + Thread* thread = NULL; { - COMPlusThrow(kNullReferenceException, W("NullReference_This")); - } + GCX_COOP(); + THREADBASEREF threadRef = (THREADBASEREF)t.Get(); + if (threadRef == NULL) + COMPlusThrow(kNullReferenceException, W("NullReference_This")); - Thread* thread = refThis->GetInternal(); + thread = threadRef->GetInternal(); - if (ThreadIsDead(thread)) - { - COMPlusThrow(kThreadStateException, W("ThreadState_Dead_State")); + if (ThreadIsDead(thread)) + COMPlusThrow(kThreadStateException, W("ThreadState_Dead_State")); } retVal = thread->GetApartment(); @@ -686,12 +582,45 @@ FCIMPL1(INT32, ThreadNative::GetApartmentState, ThreadBaseObject* pThisUNSAFE) } #endif // FEATURE_COMINTEROP - HELPER_METHOD_FRAME_END(); - + END_QCALL; return retVal; } -FCIMPLEND +// Indicate whether the thread will host an STA (this may fail if the thread has +// already been made part of the MTA, use GetApartmentState or the return state +// from this routine to check for this). +extern "C" INT32 QCALLTYPE ThreadNative_SetApartmentState(QCall::ObjectHandleOnStack t, INT32 iState) +{ + QCALL_CONTRACT; + + INT32 retVal = 0; + + BEGIN_QCALL; + + Thread* thread = NULL; + { + GCX_COOP(); + THREADBASEREF threadRef = (THREADBASEREF)t.Get(); + if (threadRef == NULL) + COMPlusThrow(kNullReferenceException, W("NullReference_This")); + + thread = threadRef->GetInternal(); + } + + // We can only change the apartment if the thread is unstarted or + // running, and if it's running we have to be in the thread's + // context. + if (!ThreadNotStarted(thread) + && (!ThreadIsRunning(thread) || (GetThread() != thread))) + { + COMPlusThrow(kThreadStateException); + } + + retVal = thread->SetApartment((Thread::ApartmentState)iState); + + END_QCALL; + return retVal; +} #endif // FEATURE_COMINTEROP_APARTMENT_SUPPORT void ReleaseThreadExternalCount(Thread * pThread) @@ -703,23 +632,23 @@ void ReleaseThreadExternalCount(Thread * pThread) typedef Holder ThreadExternalCountHolder; // Wait for the thread to die -BOOL ThreadNative::DoJoin(THREADBASEREF DyingThread, INT32 timeout) +static BOOL DoJoin(THREADBASEREF dyingThread, INT32 timeout) { CONTRACTL { THROWS; GC_TRIGGERS; MODE_COOPERATIVE; - PRECONDITION(DyingThread != NULL); + PRECONDITION(dyingThread != NULL); PRECONDITION((timeout >= 0) || (timeout == INFINITE_TIMEOUT)); } CONTRACTL_END; - Thread * DyingInternal = DyingThread->GetInternal(); + Thread* DyingInternal = dyingThread->GetInternal(); // Validate the handle. It's valid to Join a thread that's not running -- so // long as it was once started. - if (DyingInternal == 0 || + if (DyingInternal == NULL || !(DyingInternal->m_State & Thread::TS_LegalToJoin)) { COMPlusThrow(kThreadStateException, W("ThreadState_NotStarted")); @@ -730,12 +659,8 @@ BOOL ThreadNative::DoJoin(THREADBASEREF DyingThread, INT32 timeout) if (ThreadIsDead(DyingInternal) || !DyingInternal->HasValidThreadHandle()) return TRUE; - DWORD dwTimeOut32 = (timeout == INFINITE_TIMEOUT - ? INFINITE - : (DWORD) timeout); - - // There is a race here. DyingThread is going to close its thread handle. - // If we grab the handle and then DyingThread closes it, we will wait forever + // There is a race here. The Thread is going to close its thread handle. + // If we grab the handle and then the Thread closes it, we will wait forever // in DoAppropriateWait. int RefCount = DyingInternal->IncExternalCount(); if (RefCount == 1) @@ -756,8 +681,11 @@ BOOL ThreadNative::DoJoin(THREADBASEREF DyingThread, INT32 timeout) } GCX_PREEMP(); - DWORD rv = DyingInternal->JoinEx(dwTimeOut32, (WaitMode)(WaitMode_Alertable/*alertable*/|WaitMode_InDeadlock)); + DWORD dwTimeOut32 = (timeout == INFINITE_TIMEOUT + ? INFINITE + : (DWORD) timeout); + DWORD rv = DyingInternal->JoinEx(dwTimeOut32, (WaitMode)(WaitMode_Alertable/*alertable*/|WaitMode_InDeadlock)); switch(rv) { case WAIT_OBJECT_0: @@ -779,6 +707,22 @@ BOOL ThreadNative::DoJoin(THREADBASEREF DyingThread, INT32 timeout) return FALSE; } +extern "C" BOOL QCALLTYPE ThreadNative_Join(QCall::ObjectHandleOnStack thread, INT32 Timeout) +{ + QCALL_CONTRACT; + + BOOL retVal = FALSE; + + BEGIN_QCALL; + + GCX_COOP(); + retVal = DoJoin((THREADBASEREF)thread.Get(), Timeout); + + END_QCALL; + + return retVal; +} + // If the exposed object is created after-the-fact, for an existing thread, we call // InitExisting on it. This is the other "construction", as opposed to SetDelegate. void ThreadBaseObject::InitExisting() diff --git a/src/coreclr/vm/comsynchronizable.h b/src/coreclr/vm/comsynchronizable.h index b0f5b72295a15..9180216deeea9 100644 --- a/src/coreclr/vm/comsynchronizable.h +++ b/src/coreclr/vm/comsynchronizable.h @@ -52,20 +52,11 @@ friend class ThreadBaseObject; ThreadAbortRequested = 128, }; - static FCDECL1(INT32, GetPriority, ThreadBaseObject* pThisUNSAFE); - static FCDECL2(void, SetPriority, ThreadBaseObject* pThisUNSAFE, INT32 iPriority); static FCDECL1(FC_BOOL_RET, IsAlive, ThreadBaseObject* pThisUNSAFE); - static FCDECL2(FC_BOOL_RET, Join, ThreadBaseObject* pThisUNSAFE, INT32 Timeout); static FCDECL1(void, Initialize, ThreadBaseObject* pThisUNSAFE); static FCDECL1(FC_BOOL_RET, GetIsBackground, ThreadBaseObject* pThisUNSAFE); static FCDECL1(INT32, GetThreadState, ThreadBaseObject* pThisUNSAFE); -#ifdef FEATURE_COMINTEROP_APARTMENT_SUPPORT - static FCDECL1(INT32, GetApartmentState, ThreadBaseObject* pThis); - static FCDECL2(INT32, SetApartmentState, ThreadBaseObject* pThisUNSAFE, INT32 iState); -#endif // FEATURE_COMINTEROP_APARTMENT_SUPPORT - - static FCDECL0(INT32, GetOptimalMaxSpinWaitsPerSpinIteration); static FCDECL0(Object*, GetCurrentThread); static FCDECL1(void, Finalize, ThreadBaseObject* pThis); @@ -84,14 +75,21 @@ friend class ThreadBaseObject; static void KickOffThread_Worker(LPVOID /* KickOffThread_Args* */); static ULONG WINAPI KickOffThread(void *pass); - static BOOL DoJoin(THREADBASEREF DyingThread, INT32 timeout); }; 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_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(); + +#ifdef FEATURE_COMINTEROP_APARTMENT_SUPPORT +extern "C" INT32 QCALLTYPE ThreadNative_GetApartmentState(QCall::ObjectHandleOnStack t); +extern "C" INT32 QCALLTYPE ThreadNative_SetApartmentState(QCall::ObjectHandleOnStack t, INT32 iState); +#endif // FEATURE_COMINTEROP_APARTMENT_SUPPORT + +extern "C" BOOL QCALLTYPE ThreadNative_Join(QCall::ObjectHandleOnStack thread, INT32 Timeout); extern "C" void QCALLTYPE ThreadNative_Abort(QCall::ThreadHandle thread); extern "C" void QCALLTYPE ThreadNative_ResetAbort(); extern "C" void QCALLTYPE ThreadNative_SpinWait(INT32 iterations); diff --git a/src/coreclr/vm/comutilnative.cpp b/src/coreclr/vm/comutilnative.cpp index a4f0eca49a330..f15b1085ebab4 100644 --- a/src/coreclr/vm/comutilnative.cpp +++ b/src/coreclr/vm/comutilnative.cpp @@ -78,29 +78,26 @@ FCIMPLEND // Given an exception object, this method will mark its stack trace as frozen and return it to the caller. // Frozen stack traces are immutable, when a thread attempts to add a frame to it, the stack trace is cloned first. -FCIMPL1(Object *, ExceptionNative::GetFrozenStackTrace, Object* pExceptionObjectUnsafe); +extern "C" void QCALLTYPE ExceptionNative_GetFrozenStackTrace(QCall::ObjectHandleOnStack exception, QCall::ObjectHandleOnStack ret) { - CONTRACTL - { - FCALL_CHECK; - } - CONTRACTL_END; + QCALL_CONTRACT; + + BEGIN_QCALL; + + GCX_COOP(); - ASSERT(pExceptionObjectUnsafe != NULL); + _ASSERTE(exception.Get() != NULL); struct { StackTraceArray stackTrace; EXCEPTIONREF refException = NULL; PTRARRAYREF keepAliveArray = NULL; // Object array of Managed Resolvers / AssemblyLoadContexts - OBJECTREF result = NULL; } gc; - - // GC protect the array reference - HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc); + GCPROTECT_BEGIN(gc); // Get the exception object reference - gc.refException = (EXCEPTIONREF)(ObjectToOBJECTREF(pExceptionObjectUnsafe)); + gc.refException = (EXCEPTIONREF)exception.Get(); gc.refException->GetStackTrace(gc.stackTrace, &gc.keepAliveArray); @@ -108,22 +105,20 @@ FCIMPL1(Object *, ExceptionNative::GetFrozenStackTrace, Object* pExceptionObject if (gc.keepAliveArray != NULL) { - gc.result = gc.keepAliveArray; + ret.Set(gc.keepAliveArray); } else { - gc.result = gc.stackTrace.Get(); + ret.Set(gc.stackTrace.Get()); } + GCPROTECT_END(); - HELPER_METHOD_FRAME_END(); - - return OBJECTREFToObject(gc.result); + END_QCALL; } -FCIMPLEND #ifdef FEATURE_COMINTEROP -BSTR BStrFromString(STRINGREF s) +static BSTR BStrFromString(STRINGREF s) { CONTRACTL { @@ -926,34 +921,30 @@ FCIMPLEND /*===============================AllocateNewArray=============================== **Action: Allocates a new array object. Allows passing extra flags -**Returns: The allocated array. -**Arguments: elementTypeHandle -> type of the element, -** length -> number of elements, -** zeroingOptional -> whether caller prefers to skip clearing the content of the array, if possible. +**Arguments: typeHandlePtr -> TypeHandle pointer of array, +** length -> Number of elements, +** flags -> Flags that impact allocated memory, +** ret -> The allocated array. **Exceptions: IDS_EE_ARRAY_DIMENSIONS_EXCEEDED when size is too large. OOM if can't allocate. ==============================================================================*/ -FCIMPL3(Object*, GCInterface::AllocateNewArray, void* arrayTypeHandle, INT32 length, INT32 flags) +extern "C" void QCALLTYPE GCInterface_AllocateNewArray(void* typeHandlePtr, INT32 length, INT32 flags, QCall::ObjectHandleOnStack ret) { - CONTRACTL { - FCALL_CHECK; - } CONTRACTL_END; + QCALL_CONTRACT; + _ASSERTE(typeHandlePtr != NULL); + + BEGIN_QCALL; - OBJECTREF pRet = NULL; - TypeHandle arrayType = TypeHandle::FromPtr(arrayTypeHandle); + GCX_COOP(); - HELPER_METHOD_FRAME_BEGIN_RET_0(); + TypeHandle typeHandle = TypeHandle::FromPtr(typeHandlePtr); + _ASSERTE(typeHandle.IsArray()); //Only the following flags are used by GC.cs, so we'll just assert it here. _ASSERTE((flags & ~(GC_ALLOC_ZEROING_OPTIONAL | GC_ALLOC_PINNED_OBJECT_HEAP)) == 0); + ret.Set(AllocateSzArray(typeHandle, length, (GC_ALLOC_FLAGS)flags)); - pRet = AllocateSzArray(arrayType, length, (GC_ALLOC_FLAGS)flags); - - HELPER_METHOD_FRAME_END(); - - return OBJECTREFToObject(pRet); + END_QCALL; } -FCIMPLEND - FCIMPL0(INT64, GCInterface::GetTotalAllocatedBytesApproximate) { diff --git a/src/coreclr/vm/comutilnative.h b/src/coreclr/vm/comutilnative.h index a0cea8d190d59..ef41239a6bb0f 100644 --- a/src/coreclr/vm/comutilnative.h +++ b/src/coreclr/vm/comutilnative.h @@ -41,7 +41,6 @@ class ExceptionNative static FCDECL1(FC_BOOL_RET, IsImmutableAgileException, Object* pExceptionUNSAFE); static FCDECL1(FC_BOOL_RET, IsTransient, INT32 hresult); static FCDECL0(VOID, PrepareForForeignExceptionRaise); - static FCDECL1(Object *, GetFrozenStackTrace, Object* pExceptionObjectUnsafe); #ifdef FEATURE_COMINTEROP // NOTE: caller cleans up any partially initialized BSTRs in pED @@ -54,6 +53,8 @@ class ExceptionNative static FCDECL0(UINT32, GetExceptionCount); }; +extern "C" void QCALLTYPE ExceptionNative_GetFrozenStackTrace(QCall::ObjectHandleOnStack exception, QCall::ObjectHandleOnStack ret); + enum class ExceptionMessageKind { ThreadAbort = 1, ThreadInterrupted = 2, @@ -182,8 +183,6 @@ class GCInterface { static FCDECL0(INT64, GetAllocatedBytesForCurrentThread); static FCDECL0(INT64, GetTotalAllocatedBytesApproximate); - static FCDECL3(Object*, AllocateNewArray, void* elementTypeHandle, INT32 length, INT32 flags); - NOINLINE static void SendEtwRemoveMemoryPressureEvent(UINT64 bytesAllocated); static void SendEtwAddMemoryPressureEvent(UINT64 bytesAllocated); @@ -203,6 +202,8 @@ class GCInterface { extern "C" INT64 QCALLTYPE GCInterface_GetTotalAllocatedBytesPrecise(); +extern "C" void QCALLTYPE GCInterface_AllocateNewArray(void* typeHandlePtr, INT32 length, INT32 flags, QCall::ObjectHandleOnStack ret); + extern "C" INT64 QCALLTYPE GCInterface_GetTotalMemory(); extern "C" void QCALLTYPE GCInterface_Collect(INT32 generation, INT32 mode); 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/corelib.h b/src/coreclr/vm/corelib.h index 25d0163e4f172..ec5ee0795a504 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -835,6 +835,7 @@ DEFINE_FIELD_U(_name, ThreadBaseObject, m_Name) DEFINE_FIELD_U(_startHelper, ThreadBaseObject, m_StartHelper) DEFINE_FIELD_U(_DONT_USE_InternalThread, ThreadBaseObject, m_InternalThread) DEFINE_FIELD_U(_priority, ThreadBaseObject, m_Priority) +DEFINE_FIELD_U(_isDead, ThreadBaseObject, m_IsDead) DEFINE_CLASS(THREAD, Threading, Thread) DEFINE_METHOD(THREAD, START_CALLBACK, StartCallback, IM_RetVoid) #ifdef FEATURE_OBJCMARSHAL 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 69f9747a97cd1..48edcc4d04672 100644 --- a/src/coreclr/vm/ecalllist.h +++ b/src/coreclr/vm/ecalllist.h @@ -83,7 +83,6 @@ FCFuncEnd() FCFuncStart(gExceptionFuncs) FCFuncElement("IsImmutableAgileException", ExceptionNative::IsImmutableAgileException) FCFuncElement("PrepareForForeignExceptionRaise", ExceptionNative::PrepareForForeignExceptionRaise) - FCFuncElement("GetFrozenStackTrace", ExceptionNative::GetFrozenStackTrace) FCFuncElement("GetExceptionCount", ExceptionNative::GetExceptionCount) FCFuncEnd() @@ -110,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) @@ -306,14 +305,7 @@ FCFuncStart(gThreadFuncs) FCFuncElement("GetIsBackground", ThreadNative::GetIsBackground) FCFuncElement("get_IsThreadPoolThread", ThreadNative::IsThreadpoolThread) FCFuncElement("set_IsThreadPoolThread", ThreadNative::SetIsThreadpoolThread) - FCFuncElement("GetPriorityNative", ThreadNative::GetPriority) - FCFuncElement("SetPriorityNative", ThreadNative::SetPriority) FCFuncElement("GetThreadStateNative", ThreadNative::GetThreadState) -#ifdef FEATURE_COMINTEROP_APARTMENT_SUPPORT - FCFuncElement("GetApartmentStateNative", ThreadNative::GetApartmentState) - FCFuncElement("SetApartmentStateNative", ThreadNative::SetApartmentState) -#endif // FEATURE_COMINTEROP_APARTMENT_SUPPORT - FCFuncElement("Join", ThreadNative::Join) FCFuncElement("get_OptimalMaxSpinWaitsPerSpinIteration", ThreadNative::GetOptimalMaxSpinWaitsPerSpinIteration) FCFuncEnd() @@ -321,12 +313,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) @@ -364,8 +350,6 @@ FCFuncStart(gGCInterfaceFuncs) FCFuncElement("GetAllocatedBytesForCurrentThread", GCInterface::GetAllocatedBytesForCurrentThread) FCFuncElement("GetTotalAllocatedBytesApproximate", GCInterface::GetTotalAllocatedBytesApproximate) - - FCFuncElement("AllocateNewArray", GCInterface::AllocateNewArray) FCFuncEnd() FCFuncStart(gGCSettingsFuncs) @@ -503,7 +487,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 cd5ca66f660fa..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 @@ -844,7 +846,7 @@ LOADERHANDLE LoaderAllocator::AllocateHandle(OBJECTREF value) } else { - OBJECTREF* pRef = GetDomain()->AllocateObjRefPtrsInLargeTable(1); + OBJECTREF* pRef = AppDomain::GetCurrentDomain()->AllocateObjRefPtrsInLargeTable(1); SetObjectReference(pRef, gc.value); retVal = (((UINT_PTR)pRef) + 1); } @@ -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()) { @@ -2384,7 +2384,7 @@ void LoaderAllocator::AllocateGCHandlesBytesForStaticVariables(DynamicStaticsInf } else { - GetDomain()->AllocateObjRefPtrsInLargeTable(cSlots, pStaticsInfo, pMTToFillWithStaticBoxes, isClassInitedByUpdatingStaticPointer); + AppDomain::GetCurrentDomain()->AllocateObjRefPtrsInLargeTable(cSlots, pStaticsInfo, pMTToFillWithStaticBoxes, isClassInitedByUpdatingStaticPointer); } } #endif // !DACCESS_COMPILE 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/multicorejit.cpp b/src/coreclr/vm/multicorejit.cpp index d052cbeb3d903..611a32543e71f 100644 --- a/src/coreclr/vm/multicorejit.cpp +++ b/src/coreclr/vm/multicorejit.cpp @@ -768,7 +768,7 @@ DWORD MulticoreJitRecorder::EncodeModule(Module * pReferencedModule) } // Enumerate all modules within an assembly, call OnModule virtual method -HRESULT MulticoreJitModuleEnumerator::HandleAssembly(DomainAssembly * pAssembly) +HRESULT MulticoreJitModuleEnumerator::HandleAssembly(Assembly * pAssembly) { STANDARD_VM_CONTRACT; @@ -791,7 +791,7 @@ HRESULT MulticoreJitModuleEnumerator::EnumerateLoadedModules(AppDomain * pDomain while (appIt.Next(pDomainAssembly.This()) && SUCCEEDED(hr)) { { - hr = HandleAssembly(pDomainAssembly); + hr = HandleAssembly(pDomainAssembly->GetAssembly()); } } diff --git a/src/coreclr/vm/multicorejitimpl.h b/src/coreclr/vm/multicorejitimpl.h index be57644071d04..63400e7cb2012 100644 --- a/src/coreclr/vm/multicorejitimpl.h +++ b/src/coreclr/vm/multicorejitimpl.h @@ -253,7 +253,7 @@ class MulticoreJitModuleEnumerator public: HRESULT EnumerateLoadedModules(AppDomain * pDomain); - HRESULT HandleAssembly(DomainAssembly * pAssembly); + HRESULT HandleAssembly(Assembly * pAssembly); }; @@ -306,7 +306,7 @@ friend class MulticoreJitRecorder; HRESULT ReadCheckFile(const WCHAR * pFileName); - DomainAssembly * LoadAssembly(SString & assemblyName); + Assembly * LoadAssembly(SString & assemblyName); public: @@ -632,8 +632,6 @@ class MulticoreJitRecorder unsigned RecordModuleInfo(Module * pModule); void RecordOrUpdateModuleInfo(FileLoadLevel needLevel, unsigned moduleIndex); - void AddAllModulesInAsm(DomainAssembly * pAssembly); - HRESULT WriteOutput(IStream * pStream); HRESULT WriteOutput(); diff --git a/src/coreclr/vm/multicorejitplayer.cpp b/src/coreclr/vm/multicorejitplayer.cpp index 4d810bd7d9c56..c49d9eac3d9c9 100644 --- a/src/coreclr/vm/multicorejitplayer.cpp +++ b/src/coreclr/vm/multicorejitplayer.cpp @@ -780,13 +780,13 @@ HRESULT MulticoreJitProfilePlayer::HandleModuleInfoRecord(unsigned moduleTo, uns assemblyName.SetASCII(mod.m_pRecord->GetAssemblyName(), mod.m_pRecord->AssemblyNameLen()); // Load the assembly. - DomainAssembly * pDomainAssembly = LoadAssembly(assemblyName); + Assembly * pAssembly = LoadAssembly(assemblyName); - if (pDomainAssembly) + if (pAssembly) { // If we successfully loaded the assembly, enumerate the modules in the assembly // and update all modules status. - moduleEnumerator.HandleAssembly(pDomainAssembly); + moduleEnumerator.HandleAssembly(pAssembly); if (mod.m_pModule == NULL) { @@ -819,7 +819,7 @@ HRESULT MulticoreJitProfilePlayer::HandleModuleInfoRecord(unsigned moduleTo, uns return hr; } -DomainAssembly * MulticoreJitProfilePlayer::LoadAssembly(SString & assemblyName) +Assembly * MulticoreJitProfilePlayer::LoadAssembly(SString & assemblyName) { STANDARD_VM_CONTRACT; @@ -839,7 +839,7 @@ DomainAssembly * MulticoreJitProfilePlayer::LoadAssembly(SString & assemblyName) } // Bind and load the assembly. - return spec.LoadDomainAssembly( + return spec.LoadAssembly( FILE_LOADED, FALSE); // Don't throw on FileNotFound. } diff --git a/src/coreclr/vm/object.h b/src/coreclr/vm/object.h index 7fa562e509a39..c6a644a03edde 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 { @@ -1333,6 +1326,9 @@ class ThreadBaseObject : public Object // Only used by managed code, see comment there bool m_MayNeedResetForThreadPool; + // Set in unmanaged code and read in managed code. + bool m_IsDead; + protected: // the ctor and dtor can do no useful work. ThreadBaseObject() {LIMITED_METHOD_CONTRACT;}; @@ -1384,6 +1380,12 @@ class ThreadBaseObject : public Object LIMITED_METHOD_CONTRACT; return m_Priority; } + + void SetIsDead() + { + LIMITED_METHOD_CONTRACT; + m_IsDead = true; + } }; // MarshalByRefObjectBaseObject @@ -1430,8 +1432,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/peassembly.cpp b/src/coreclr/vm/peassembly.cpp index 3f54dbff556af..df387a828b0da 100644 --- a/src/coreclr/vm/peassembly.cpp +++ b/src/coreclr/vm/peassembly.cpp @@ -575,11 +575,11 @@ BOOL PEAssembly::GetResource(LPCSTR szName, DWORD *cbResource, AssemblySpec spec; spec.InitializeSpec(mdLinkRef, GetMDImport(), pAssembly); - DomainAssembly* pDomainAssembly = spec.LoadDomainAssembly(FILE_LOADED); + Assembly* pLoadedAssembly = spec.LoadAssembly(FILE_LOADED); if (dwLocation) { if (pAssemblyRef) - *pAssemblyRef = pDomainAssembly->GetAssembly(); + *pAssemblyRef = pLoadedAssembly; *dwLocation = *dwLocation | 2; // ResourceLocation.containedInAnotherAssembly } @@ -590,7 +590,7 @@ BOOL PEAssembly::GetResource(LPCSTR szName, DWORD *cbResource, pAssemblyRef, szFileName, dwLocation, - pDomainAssembly->GetAssembly()); + pLoadedAssembly); } case mdtFile: diff --git a/src/coreclr/vm/qcallentrypoints.cpp b/src/coreclr/vm/qcallentrypoints.cpp index 9eb0584379516..02ad38c982128 100644 --- a/src/coreclr/vm/qcallentrypoints.cpp +++ b/src/coreclr/vm/qcallentrypoints.cpp @@ -99,6 +99,7 @@ static const Entry s_QCall[] = DllImportEntry(Environment_Exit) DllImportEntry(Environment_FailFast) DllImportEntry(Environment_GetProcessorCount) + DllImportEntry(ExceptionNative_GetFrozenStackTrace) DllImportEntry(ExceptionNative_GetMessageFromNativeResources) DllImportEntry(ExceptionNative_GetMethodFromStackTrace) DllImportEntry(ExceptionNative_ThrowAmbiguousResolutionException) @@ -117,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) @@ -157,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) @@ -233,10 +237,16 @@ static const Entry s_QCall[] = DllImportEntry(String_IsInterned) DllImportEntry(AppDomain_CreateDynamicAssembly) DllImportEntry(ThreadNative_Start) + DllImportEntry(ThreadNative_SetPriority) DllImportEntry(ThreadNative_SetIsBackground) DllImportEntry(ThreadNative_InformThreadNameChange) DllImportEntry(ThreadNative_YieldThread) DllImportEntry(ThreadNative_GetCurrentOSThreadId) +#ifdef FEATURE_COMINTEROP_APARTMENT_SUPPORT + DllImportEntry(ThreadNative_GetApartmentState) + DllImportEntry(ThreadNative_SetApartmentState) +#endif // FEATURE_COMINTEROP_APARTMENT_SUPPORT + DllImportEntry(ThreadNative_Join) DllImportEntry(ThreadNative_Abort) DllImportEntry(ThreadNative_ResetAbort) DllImportEntry(ThreadNative_SpinWait) @@ -245,9 +255,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) @@ -258,6 +271,7 @@ static const Entry s_QCall[] = DllImportEntry(GCInterface_WaitForFullGCComplete) DllImportEntry(GCInterface_StartNoGCRegion) DllImportEntry(GCInterface_EndNoGCRegion) + DllImportEntry(GCInterface_AllocateNewArray) DllImportEntry(GCInterface_GetTotalMemory) DllImportEntry(GCInterface_Collect) DllImportEntry(GCInterface_ReRegisterForFinalize) diff --git a/src/coreclr/vm/readytoruninfo.cpp b/src/coreclr/vm/readytoruninfo.cpp index dbd68d919690b..19ab4b621469b 100644 --- a/src/coreclr/vm/readytoruninfo.cpp +++ b/src/coreclr/vm/readytoruninfo.cpp @@ -1526,7 +1526,7 @@ class NativeManifestModule : public ModuleBase return GetModuleIfLoaded(kFile); } - DomainAssembly * LoadAssemblyImpl(mdAssemblyRef kAssemblyRef) final + Assembly * LoadAssemblyImpl(mdAssemblyRef kAssemblyRef) final { STANDARD_VM_CONTRACT; // Since we can only load via ModuleRef, this should never fail unless the module is improperly formatted 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 8c60b2b5a7982..99a366e9a2f13 100644 --- a/src/coreclr/vm/threads.cpp +++ b/src/coreclr/vm/threads.cpp @@ -2765,6 +2765,10 @@ void Thread::CooperativeCleanup() // Clear out the alloc context pointer for this thread. When TLS is gone, this pointer will point into freed memory. m_pRuntimeThreadLocals = nullptr; } + + OBJECTREF threadObjMaybe = GetExposedObjectRaw(); + if (threadObjMaybe != NULL) + ((THREADBASEREF)threadObjMaybe)->SetIsDead(); } // See general comments on thread destruction (code:#threadDestruction) above. @@ -3112,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. @@ -4781,20 +4785,6 @@ Thread::ApartmentState Thread::GetFinalApartment() return as; } -// when we get apartment tear-down notification, -// we want reset the apartment state we cache on the thread -VOID Thread::ResetApartment() -{ - CONTRACTL { - NOTHROW; - GC_NOTRIGGER; - } - CONTRACTL_END; - - // reset the TS_InSTA bit and TS_InMTA bit - ResetThreadState((Thread::ThreadState)(TS_InSTA | TS_InMTA)); -} - // Attempt to set current thread's apartment state. The actual apartment state // achieved is returned and may differ from the input state if someone managed // to call CoInitializeEx on this thread first (note that calls to SetApartment diff --git a/src/coreclr/vm/threads.h b/src/coreclr/vm/threads.h index 6aa3e04b00465..f3b7894c3dea6 100644 --- a/src/coreclr/vm/threads.h +++ b/src/coreclr/vm/threads.h @@ -2168,10 +2168,6 @@ class Thread // call CoInitializeEx on this thread first (note that calls to SetApartment made // before the thread has started are guaranteed to succeed). ApartmentState SetApartment(ApartmentState state); - - // when we get apartment tear-down notification, - // we want reset the apartment state we cache on the thread - VOID ResetApartment(); #endif // FEATURE_COMINTEROP_APARTMENT_SUPPORT // Either perform WaitForSingleObject or MsgWaitForSingleObject as appropriate. 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/coreclr/vm/zapsig.cpp b/src/coreclr/vm/zapsig.cpp index 87d679e34b4d0..f4d1b7962f212 100644 --- a/src/coreclr/vm/zapsig.cpp +++ b/src/coreclr/vm/zapsig.cpp @@ -579,7 +579,7 @@ ModuleBase *ZapSig::DecodeModuleFromIndex(Module *fromModule, } else { - pAssembly = fromModule->LoadAssembly(RidToToken(index, mdtAssemblyRef))->GetAssembly(); + pAssembly = fromModule->LoadAssembly(RidToToken(index, mdtAssemblyRef)); } } else diff --git a/src/libraries/Fuzzing/DotnetFuzzing/Assert.cs b/src/libraries/Fuzzing/DotnetFuzzing/Assert.cs index 810174ccbc131..a5f2a9dd1d195 100644 --- a/src/libraries/Fuzzing/DotnetFuzzing/Assert.cs +++ b/src/libraries/Fuzzing/DotnetFuzzing/Assert.cs @@ -18,6 +18,17 @@ static void Throw(T expected, T actual) => throw new Exception($"Expected={expected} Actual={actual}"); } + public static void NotNull(T value) + { + if (value == null) + { + ThrowNull(); + } + + static void ThrowNull() => + throw new Exception("Value is null"); + } + public static void SequenceEqual(ReadOnlySpan expected, ReadOnlySpan actual) { if (!expected.SequenceEqual(actual)) diff --git a/src/libraries/Fuzzing/DotnetFuzzing/Dictionaries/nrbfdecoder.dict b/src/libraries/Fuzzing/DotnetFuzzing/Dictionaries/nrbfdecoder.dict new file mode 100644 index 0000000000000..1b8f14f961cc1 --- /dev/null +++ b/src/libraries/Fuzzing/DotnetFuzzing/Dictionaries/nrbfdecoder.dict @@ -0,0 +1,16 @@ +# "Hello World!" +"\x00\x01\x00\x00\x00\xFF\xFF\xFF\xFF\x01\x00\x00\x00\x00\x00\x00\x00\x06\x01\x00\x00\x00\x0C\x48\x65\x6C\x6C\x6F\x20\x57\x6F\x72\x6C\x64\x21\x0B" +# new DateTime(2024, 2, 29) +"\x00\x01\x00\x00\x00\xFF\xFF\xFF\xFF\x01\x00\x00\x00\x00\x00\x00\x00\x04\x01\x00\x00\x00\x0F\x53\x79\x73\x74\x65\x6D\x2E\x44\x61\x74\x65\x54\x69\x6D\x65\x02\x00\x00\x00\x05\x74\x69\x63\x6B\x73\x08\x64\x61\x74\x65\x44\x61\x74\x61\x00\x00\x09\x10\x00\x00\x60\x5F\xB9\x38\xDC\x08\x00\x00\x60\x5F\xB9\x38\xDC\x08\x0B" +# new int[] { 1, 2, 3 } +"\x00\x01\x00\x00\x00\xFF\xFF\xFF\xFF\x01\x00\x00\x00\x00\x00\x00\x00\x0F\x01\x00\x00\x00\x03\x00\x00\x00\x08\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x0B" +# new object[] { int.MaxValue, "string", null } +"\x00\x01\x00\x00\x00\xFF\xFF\xFF\xFF\x01\x00\x00\x00\x00\x00\x00\x00\x10\x01\x00\x00\x00\x03\x00\x00\x00\x08\x08\xFF\xFF\xFF\x7F\x06\x02\x00\x00\x00\x06\x73\x74\x72\x69\x6E\x67\x0A\x0B" +# new int?[Array.MaxLength] (plenty of nulls) +"\x00\x01\x00\x00\x00\xFF\xFF\xFF\xFF\x01\x00\x00\x00\x00\x00\x00\x00\x07\x01\x00\x00\x00\x00\x01\x00\x00\x00\xC7\xFF\xFF\x7F\x03\x6E\x53\x79\x73\x74\x65\x6D\x2E\x4E\x75\x6C\x6C\x61\x62\x6C\x65\x60\x31\x5B\x5B\x53\x79\x73\x74\x65\x6D\x2E\x49\x6E\x74\x33\x32\x2C\x20\x6D\x73\x63\x6F\x72\x6C\x69\x62\x2C\x20\x56\x65\x72\x73\x69\x6F\x6E\x3D\x34\x2E\x30\x2E\x30\x2E\x30\x2C\x20\x43\x75\x6C\x74\x75\x72\x65\x3D\x6E\x65\x75\x74\x72\x61\x6C\x2C\x20\x50\x75\x62\x6C\x69\x63\x4B\x65\x79\x54\x6F\x6B\x65\x6E\x3D\x62\x37\x37\x61\x35\x63\x35\x36\x31\x39\x33\x34\x65\x30\x38\x39\x5D\x5D\x0E\xC7\xFF\xFF\x7F\x0B" +# [["jagged", "array"], ["of", "strings"]] +"\x00\x01\x00\x00\x00\xFF\xFF\xFF\xFF\x01\x00\x00\x00\x00\x00\x00\x00\x07\x01\x00\x00\x00\x01\x01\x00\x00\x00\x02\x00\x00\x00\x06\x09\x02\x00\x00\x00\x09\x03\x00\x00\x00\x11\x02\x00\x00\x00\x02\x00\x00\x00\x06\x04\x00\x00\x00\x06\x6A\x61\x67\x67\x65\x64\x06\x05\x00\x00\x00\x05\x61\x72\x72\x61\x79\x11\x03\x00\x00\x00\x02\x00\x00\x00\x06\x06\x00\x00\x00\x02\x6F\x66\x06\x07\x00\x00\x00\x07\x73\x74\x72\x69\x6E\x67\x73\x0B" +# new Dictionary { { "1", true }, { "2", false } } +"\x00\x01\x00\x00\x00\xFF\xFF\xFF\xFF\x01\x00\x00\x00\x00\x00\x00\x00\x04\x01\x00\x00\x00\xE3\x01\x53\x79\x73\x74\x65\x6D\x2E\x43\x6F\x6C\x6C\x65\x63\x74\x69\x6F\x6E\x73\x2E\x47\x65\x6E\x65\x72\x69\x63\x2E\x44\x69\x63\x74\x69\x6F\x6E\x61\x72\x79\x60\x32\x5B\x5B\x53\x79\x73\x74\x65\x6D\x2E\x53\x74\x72\x69\x6E\x67\x2C\x20\x6D\x73\x63\x6F\x72\x6C\x69\x62\x2C\x20\x56\x65\x72\x73\x69\x6F\x6E\x3D\x34\x2E\x30\x2E\x30\x2E\x30\x2C\x20\x43\x75\x6C\x74\x75\x72\x65\x3D\x6E\x65\x75\x74\x72\x61\x6C\x2C\x20\x50\x75\x62\x6C\x69\x63\x4B\x65\x79\x54\x6F\x6B\x65\x6E\x3D\x62\x37\x37\x61\x35\x63\x35\x36\x31\x39\x33\x34\x65\x30\x38\x39\x5D\x2C\x5B\x53\x79\x73\x74\x65\x6D\x2E\x42\x6F\x6F\x6C\x65\x61\x6E\x2C\x20\x6D\x73\x63\x6F\x72\x6C\x69\x62\x2C\x20\x56\x65\x72\x73\x69\x6F\x6E\x3D\x34\x2E\x30\x2E\x30\x2E\x30\x2C\x20\x43\x75\x6C\x74\x75\x72\x65\x3D\x6E\x65\x75\x74\x72\x61\x6C\x2C\x20\x50\x75\x62\x6C\x69\x63\x4B\x65\x79\x54\x6F\x6B\x65\x6E\x3D\x62\x37\x37\x61\x35\x63\x35\x36\x31\x39\x33\x34\x65\x30\x38\x39\x5D\x5D\x04\x00\x00\x00\x07\x56\x65\x72\x73\x69\x6F\x6E\x08\x43\x6F\x6D\x70\x61\x72\x65\x72\x08\x48\x61\x73\x68\x53\x69\x7A\x65\x0D\x4B\x65\x79\x56\x61\x6C\x75\x65\x50\x61\x69\x72\x73\x00\x03\x00\x03\x08\x92\x01\x53\x79\x73\x74\x65\x6D\x2E\x43\x6F\x6C\x6C\x65\x63\x74\x69\x6F\x6E\x73\x2E\x47\x65\x6E\x65\x72\x69\x63\x2E\x47\x65\x6E\x65\x72\x69\x63\x45\x71\x75\x61\x6C\x69\x74\x79\x43\x6F\x6D\x70\x61\x72\x65\x72\x60\x31\x5B\x5B\x53\x79\x73\x74\x65\x6D\x2E\x53\x74\x72\x69\x6E\x67\x2C\x20\x6D\x73\x63\x6F\x72\x6C\x69\x62\x2C\x20\x56\x65\x72\x73\x69\x6F\x6E\x3D\x34\x2E\x30\x2E\x30\x2E\x30\x2C\x20\x43\x75\x6C\x74\x75\x72\x65\x3D\x6E\x65\x75\x74\x72\x61\x6C\x2C\x20\x50\x75\x62\x6C\x69\x63\x4B\x65\x79\x54\x6F\x6B\x65\x6E\x3D\x62\x37\x37\x61\x35\x63\x35\x36\x31\x39\x33\x34\x65\x30\x38\x39\x5D\x5D\x08\xE7\x01\x53\x79\x73\x74\x65\x6D\x2E\x43\x6F\x6C\x6C\x65\x63\x74\x69\x6F\x6E\x73\x2E\x47\x65\x6E\x65\x72\x69\x63\x2E\x4B\x65\x79\x56\x61\x6C\x75\x65\x50\x61\x69\x72\x60\x32\x5B\x5B\x53\x79\x73\x74\x65\x6D\x2E\x53\x74\x72\x69\x6E\x67\x2C\x20\x6D\x73\x63\x6F\x72\x6C\x69\x62\x2C\x20\x56\x65\x72\x73\x69\x6F\x6E\x3D\x34\x2E\x30\x2E\x30\x2E\x30\x2C\x20\x43\x75\x6C\x74\x75\x72\x65\x3D\x6E\x65\x75\x74\x72\x61\x6C\x2C\x20\x50\x75\x62\x6C\x69\x63\x4B\x65\x79\x54\x6F\x6B\x65\x6E\x3D\x62\x37\x37\x61\x35\x63\x35\x36\x31\x39\x33\x34\x65\x30\x38\x39\x5D\x2C\x5B\x53\x79\x73\x74\x65\x6D\x2E\x42\x6F\x6F\x6C\x65\x61\x6E\x2C\x20\x6D\x73\x63\x6F\x72\x6C\x69\x62\x2C\x20\x56\x65\x72\x73\x69\x6F\x6E\x3D\x34\x2E\x30\x2E\x30\x2E\x30\x2C\x20\x43\x75\x6C\x74\x75\x72\x65\x3D\x6E\x65\x75\x74\x72\x61\x6C\x2C\x20\x50\x75\x62\x6C\x69\x63\x4B\x65\x79\x54\x6F\x6B\x65\x6E\x3D\x62\x37\x37\x61\x35\x63\x35\x36\x31\x39\x33\x34\x65\x30\x38\x39\x5D\x5D\x5B\x5D\x02\x00\x00\x00\x09\x02\x00\x00\x00\x03\x00\x00\x00\x09\x03\x00\x00\x00\x04\x02\x00\x00\x00\x92\x01\x53\x79\x73\x74\x65\x6D\x2E\x43\x6F\x6C\x6C\x65\x63\x74\x69\x6F\x6E\x73\x2E\x47\x65\x6E\x65\x72\x69\x63\x2E\x47\x65\x6E\x65\x72\x69\x63\x45\x71\x75\x61\x6C\x69\x74\x79\x43\x6F\x6D\x70\x61\x72\x65\x72\x60\x31\x5B\x5B\x53\x79\x73\x74\x65\x6D\x2E\x53\x74\x72\x69\x6E\x67\x2C\x20\x6D\x73\x63\x6F\x72\x6C\x69\x62\x2C\x20\x56\x65\x72\x73\x69\x6F\x6E\x3D\x34\x2E\x30\x2E\x30\x2E\x30\x2C\x20\x43\x75\x6C\x74\x75\x72\x65\x3D\x6E\x65\x75\x74\x72\x61\x6C\x2C\x20\x50\x75\x62\x6C\x69\x63\x4B\x65\x79\x54\x6F\x6B\x65\x6E\x3D\x62\x37\x37\x61\x35\x63\x35\x36\x31\x39\x33\x34\x65\x30\x38\x39\x5D\x5D\x00\x00\x00\x00\x07\x03\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x03\xE5\x01\x53\x79\x73\x74\x65\x6D\x2E\x43\x6F\x6C\x6C\x65\x63\x74\x69\x6F\x6E\x73\x2E\x47\x65\x6E\x65\x72\x69\x63\x2E\x4B\x65\x79\x56\x61\x6C\x75\x65\x50\x61\x69\x72\x60\x32\x5B\x5B\x53\x79\x73\x74\x65\x6D\x2E\x53\x74\x72\x69\x6E\x67\x2C\x20\x6D\x73\x63\x6F\x72\x6C\x69\x62\x2C\x20\x56\x65\x72\x73\x69\x6F\x6E\x3D\x34\x2E\x30\x2E\x30\x2E\x30\x2C\x20\x43\x75\x6C\x74\x75\x72\x65\x3D\x6E\x65\x75\x74\x72\x61\x6C\x2C\x20\x50\x75\x62\x6C\x69\x63\x4B\x65\x79\x54\x6F\x6B\x65\x6E\x3D\x62\x37\x37\x61\x35\x63\x35\x36\x31\x39\x33\x34\x65\x30\x38\x39\x5D\x2C\x5B\x53\x79\x73\x74\x65\x6D\x2E\x42\x6F\x6F\x6C\x65\x61\x6E\x2C\x20\x6D\x73\x63\x6F\x72\x6C\x69\x62\x2C\x20\x56\x65\x72\x73\x69\x6F\x6E\x3D\x34\x2E\x30\x2E\x30\x2E\x30\x2C\x20\x43\x75\x6C\x74\x75\x72\x65\x3D\x6E\x65\x75\x74\x72\x61\x6C\x2C\x20\x50\x75\x62\x6C\x69\x63\x4B\x65\x79\x54\x6F\x6B\x65\x6E\x3D\x62\x37\x37\x61\x35\x63\x35\x36\x31\x39\x33\x34\x65\x30\x38\x39\x5D\x5D\x04\xFC\xFF\xFF\xFF\xE5\x01\x53\x79\x73\x74\x65\x6D\x2E\x43\x6F\x6C\x6C\x65\x63\x74\x69\x6F\x6E\x73\x2E\x47\x65\x6E\x65\x72\x69\x63\x2E\x4B\x65\x79\x56\x61\x6C\x75\x65\x50\x61\x69\x72\x60\x32\x5B\x5B\x53\x79\x73\x74\x65\x6D\x2E\x53\x74\x72\x69\x6E\x67\x2C\x20\x6D\x73\x63\x6F\x72\x6C\x69\x62\x2C\x20\x56\x65\x72\x73\x69\x6F\x6E\x3D\x34\x2E\x30\x2E\x30\x2E\x30\x2C\x20\x43\x75\x6C\x74\x75\x72\x65\x3D\x6E\x65\x75\x74\x72\x61\x6C\x2C\x20\x50\x75\x62\x6C\x69\x63\x4B\x65\x79\x54\x6F\x6B\x65\x6E\x3D\x62\x37\x37\x61\x35\x63\x35\x36\x31\x39\x33\x34\x65\x30\x38\x39\x5D\x2C\x5B\x53\x79\x73\x74\x65\x6D\x2E\x42\x6F\x6F\x6C\x65\x61\x6E\x2C\x20\x6D\x73\x63\x6F\x72\x6C\x69\x62\x2C\x20\x56\x65\x72\x73\x69\x6F\x6E\x3D\x34\x2E\x30\x2E\x30\x2E\x30\x2C\x20\x43\x75\x6C\x74\x75\x72\x65\x3D\x6E\x65\x75\x74\x72\x61\x6C\x2C\x20\x50\x75\x62\x6C\x69\x63\x4B\x65\x79\x54\x6F\x6B\x65\x6E\x3D\x62\x37\x37\x61\x35\x63\x35\x36\x31\x39\x33\x34\x65\x30\x38\x39\x5D\x5D\x02\x00\x00\x00\x03\x6B\x65\x79\x05\x76\x61\x6C\x75\x65\x01\x00\x01\x06\x05\x00\x00\x00\x01\x31\x01\x01\xFA\xFF\xFF\xFF\xFC\xFF\xFF\xFF\x06\x07\x00\x00\x00\x01\x32\x00\x0B" +# new ComplexType2D { I = 1, J = 2 } (non-system class) +"\x00\x01\x00\x00\x00\xFF\xFF\xFF\xFF\x01\x00\x00\x00\x00\x00\x00\x00\x0C\x02\x00\x00\x00\x3D\x42\x66\x44\x65\x6D\x6F\x2C\x20\x56\x65\x72\x73\x69\x6F\x6E\x3D\x31\x2E\x30\x2E\x30\x2E\x30\x2C\x20\x43\x75\x6C\x74\x75\x72\x65\x3D\x6E\x65\x75\x74\x72\x61\x6C\x2C\x20\x50\x75\x62\x6C\x69\x63\x4B\x65\x79\x54\x6F\x6B\x65\x6E\x3D\x6E\x75\x6C\x6C\x05\x01\x00\x00\x00\x14\x42\x66\x44\x65\x6D\x6F\x2E\x43\x6F\x6D\x70\x6C\x65\x78\x54\x79\x70\x65\x32\x44\x02\x00\x00\x00\x01\x49\x01\x4A\x00\x00\x08\x08\x02\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x0B" \ No newline at end of file diff --git a/src/libraries/Fuzzing/DotnetFuzzing/DotnetFuzzing.csproj b/src/libraries/Fuzzing/DotnetFuzzing/DotnetFuzzing.csproj index 293af0122bfb4..82f54f412ace6 100644 --- a/src/libraries/Fuzzing/DotnetFuzzing/DotnetFuzzing.csproj +++ b/src/libraries/Fuzzing/DotnetFuzzing/DotnetFuzzing.csproj @@ -30,4 +30,8 @@ + + + + diff --git a/src/libraries/Fuzzing/DotnetFuzzing/Fuzzers/AssemblyNameInfoFuzzer.cs b/src/libraries/Fuzzing/DotnetFuzzing/Fuzzers/AssemblyNameInfoFuzzer.cs index 9ce1bd255c7b6..d166726665afe 100644 --- a/src/libraries/Fuzzing/DotnetFuzzing/Fuzzers/AssemblyNameInfoFuzzer.cs +++ b/src/libraries/Fuzzing/DotnetFuzzing/Fuzzers/AssemblyNameInfoFuzzer.cs @@ -24,15 +24,15 @@ public void FuzzTarget(ReadOnlySpan bytes) using PooledBoundedMemory inputPoisonedBefore = PooledBoundedMemory.Rent(chars, PoisonPagePlacement.Before); using PooledBoundedMemory inputPoisonedAfter = PooledBoundedMemory.Rent(chars, PoisonPagePlacement.After); - Test(inputPoisonedBefore); - Test(inputPoisonedAfter); + Test(inputPoisonedBefore.Span); + Test(inputPoisonedAfter.Span); } - private static void Test(PooledBoundedMemory inputPoisoned) + private static void Test(Span span) { - if (AssemblyNameInfo.TryParse(inputPoisoned.Span, out AssemblyNameInfo? fromTryParse)) + if (AssemblyNameInfo.TryParse(span, out AssemblyNameInfo? fromTryParse)) { - AssemblyNameInfo fromParse = AssemblyNameInfo.Parse(inputPoisoned.Span); + AssemblyNameInfo fromParse = AssemblyNameInfo.Parse(span); Assert.Equal(fromTryParse.Name, fromParse.Name); Assert.Equal(fromTryParse.FullName, fromParse.FullName); @@ -66,7 +66,7 @@ private static void Test(PooledBoundedMemory inputPoisoned) { try { - _ = AssemblyNameInfo.Parse(inputPoisoned.Span); + _ = AssemblyNameInfo.Parse(span); } catch (ArgumentException) { diff --git a/src/libraries/Fuzzing/DotnetFuzzing/Fuzzers/NrbfDecoderFuzzer.cs b/src/libraries/Fuzzing/DotnetFuzzing/Fuzzers/NrbfDecoderFuzzer.cs new file mode 100644 index 0000000000000..46da18e4b0fc8 --- /dev/null +++ b/src/libraries/Fuzzing/DotnetFuzzing/Fuzzers/NrbfDecoderFuzzer.cs @@ -0,0 +1,113 @@ +// 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.Formats.Nrbf; +using System.Runtime.Serialization; +using System.Text; + +namespace DotnetFuzzing.Fuzzers +{ + internal sealed class NrbfDecoderFuzzer : IFuzzer + { + public string[] TargetAssemblies { get; } = ["System.Formats.Nrbf"]; + + public string[] TargetCoreLibPrefixes => []; + + public string Dictionary => "nrbfdecoder.dict"; + + public void FuzzTarget(ReadOnlySpan bytes) + { + using PooledBoundedMemory inputPoisonedAfter = PooledBoundedMemory.Rent(bytes, PoisonPagePlacement.After); + using PooledBoundedMemory inputPoisonedBefore = PooledBoundedMemory.Rent(bytes, PoisonPagePlacement.Before); + using MemoryStream streamAfter = new MemoryStream(inputPoisonedAfter.Memory.ToArray()); + using MemoryStream streamBefore = new MemoryStream(inputPoisonedBefore.Memory.ToArray()); + + Test(inputPoisonedAfter.Span, streamAfter); + Test(inputPoisonedBefore.Span, streamBefore); + } + + private static void Test(Span testSpan, MemoryStream stream) + { + if (NrbfDecoder.StartsWithPayloadHeader(testSpan)) + { + try + { + SerializationRecord record = NrbfDecoder.Decode(stream, out IReadOnlyDictionary recordMap); + switch (record.RecordType) + { + case SerializationRecordType.ArraySingleObject: + SZArrayRecord arrayObj = (SZArrayRecord)record; + object?[] objArray = arrayObj.GetArray(); + Assert.Equal(arrayObj.Length, objArray.Length); + Assert.Equal(1, arrayObj.Rank); + break; + case SerializationRecordType.ArraySingleString: + SZArrayRecord arrayString = (SZArrayRecord)record; + string?[] array = arrayString.GetArray(); + Assert.Equal(arrayString.Length, array.Length); + Assert.Equal(1, arrayString.Rank); + Assert.Equal(true, arrayString.TypeNameMatches(typeof(string[]))); + break; + case SerializationRecordType.ArraySinglePrimitive: + case SerializationRecordType.BinaryArray: + ArrayRecord arrayBinary = (ArrayRecord)record; + Assert.NotNull(arrayBinary.TypeName); + break; + case SerializationRecordType.BinaryObjectString: + _ = ((PrimitiveTypeRecord)record).Value; + break; + case SerializationRecordType.ClassWithId: + case SerializationRecordType.ClassWithMembersAndTypes: + case SerializationRecordType.SystemClassWithMembersAndTypes: + ClassRecord classRecord = (ClassRecord)record; + Assert.NotNull(classRecord.TypeName); + + foreach (string name in classRecord.MemberNames) + { + Assert.Equal(true, classRecord.HasMember(name)); + } + break; + case SerializationRecordType.MemberPrimitiveTyped: + PrimitiveTypeRecord primitiveType = (PrimitiveTypeRecord)record; + Assert.NotNull(primitiveType.Value); + break; + case SerializationRecordType.MemberReference: + Assert.NotNull(record.TypeName); + break; + case SerializationRecordType.BinaryLibrary: + Assert.Equal(false, record.Id.Equals(default)); + break; + case SerializationRecordType.ObjectNull: + case SerializationRecordType.ObjectNullMultiple: + case SerializationRecordType.ObjectNullMultiple256: + Assert.Equal(default, record.Id); + break; + case SerializationRecordType.MessageEnd: + case SerializationRecordType.SerializedStreamHeader: + // case SerializationRecordType.ClassWithMembers: will cause NotSupportedException + // case SerializationRecordType.SystemClassWithMembers: will cause NotSupportedException + default: + throw new Exception("Unexpected RecordType"); + } + } + catch (SerializationException) { /* Reading from the stream encountered invalid NRBF data.*/ } + catch (NotSupportedException) { /* Reading from the stream encountered unsupported records */ } + catch (DecoderFallbackException) { /* Reading from the stream encountered an invalid UTF8 sequence. */ } + catch (EndOfStreamException) { /* The end of the stream was reached before reading SerializationRecordType.MessageEnd record. */ } + catch (IOException) { /* An I/O error occurred. */ } + } + else + { + try + { + NrbfDecoder.Decode(stream); + throw new Exception("Decoding supposed to fail!"); + } + catch (SerializationException) { /* Everything has to start with a header */ } + catch (NotSupportedException) { /* Reading from the stream encountered unsupported records */ } + catch (EndOfStreamException) { /* The end of the stream was reached before reading SerializationRecordType.MessageEnd record. */ } + } + } + } +} diff --git a/src/libraries/Fuzzing/DotnetFuzzing/Fuzzers/TypeNameFuzzer.cs b/src/libraries/Fuzzing/DotnetFuzzing/Fuzzers/TypeNameFuzzer.cs index f8b3e96083707..0a189da4f18af 100644 --- a/src/libraries/Fuzzing/DotnetFuzzing/Fuzzers/TypeNameFuzzer.cs +++ b/src/libraries/Fuzzing/DotnetFuzzing/Fuzzers/TypeNameFuzzer.cs @@ -3,8 +3,6 @@ using System.Buffers; using System.Reflection.Metadata; -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.Marshalling; using System.Text; namespace DotnetFuzzing.Fuzzers @@ -55,7 +53,7 @@ private static void Test(Span testSpan) try { TypeName.Parse(testSpan); - Assert.Equal(true, false); // should never succeed + throw new Exception("Parsing was supposed to fail!"); } catch (ArgumentException) { } catch (InvalidOperationException) { } diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/ActivitySource.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/ActivitySource.cs index ebaddab4ec80c..f82e54e65d5b5 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/ActivitySource.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/ActivitySource.cs @@ -407,105 +407,94 @@ internal void NotifyActivityAddException(Activity activity, Exception exception, } } - // SynchronizedList is a helper collection which ensure thread safety on the collection - // and allow enumerating the collection items and execute some action on the enumerated item and can detect any change in the collection - // during the enumeration which force restarting the enumeration again. - // Caution: We can have the action executed on the same item more than once which is ok in our scenarios. + // This class uses a copy-on-write design to ensure thread safety all operations are thread safe. + // However, it is possible for read-only operations to see stale versions of the item while a change + // is occurring. internal sealed class SynchronizedList { - private readonly List _list; - private uint _version; - - public SynchronizedList() => _list = new List(); + private readonly object _writeLock; + // This array must not be mutated directly. To mutate, obtain the lock, copy the array and then replace it with the new array. + private T[] _volatileArray; + public SynchronizedList() + { + _volatileArray = []; + _writeLock = new(); + } public void Add(T item) { - lock (_list) + lock (_writeLock) { - _list.Add(item); - _version++; + T[] newArray = new T[_volatileArray.Length + 1]; + + Array.Copy(_volatileArray, newArray, _volatileArray.Length);// copy existing items + newArray[_volatileArray.Length] = item;// copy new item + + _volatileArray = newArray; } } public bool AddIfNotExist(T item) { - lock (_list) + lock (_writeLock) { - if (!_list.Contains(item)) + int index = Array.IndexOf(_volatileArray, item); + + if (index >= 0) { - _list.Add(item); - _version++; - return true; + return false; } - return false; + + T[] newArray = new T[_volatileArray.Length + 1]; + + Array.Copy(_volatileArray, newArray, _volatileArray.Length);// copy existing items + newArray[_volatileArray.Length] = item;// copy new item + + _volatileArray = newArray; + + return true; } } public bool Remove(T item) { - lock (_list) + lock (_writeLock) { - if (_list.Remove(item)) + int index = Array.IndexOf(_volatileArray, item); + + if (index < 0) { - _version++; - return true; + return false; } - return false; + + T[] newArray = new T[_volatileArray.Length - 1]; + + Array.Copy(_volatileArray, newArray, index);// copy existing items before index + + Array.Copy( + _volatileArray, index + 1, // position after the index, skipping it + newArray, index, _volatileArray.Length - index - 1// remaining items accounting for removed item + ); + + _volatileArray = newArray; + return true; } } - public int Count => _list.Count; + public int Count => _volatileArray.Length; public void EnumWithFunc(ActivitySource.Function func, ref ActivityCreationOptions data, ref ActivitySamplingResult samplingResult, ref ActivityCreationOptions dataWithContext) { - uint version = _version; - int index = 0; - - while (index < _list.Count) + foreach (T item in _volatileArray) { - T item; - lock (_list) - { - if (version != _version) - { - version = _version; - index = 0; - continue; - } - - item = _list[index]; - index++; - } - - // Important to call the func outside the lock. - // This is the whole point we are having this wrapper class. func(item, ref data, ref samplingResult, ref dataWithContext); } } public void EnumWithAction(Action action, object arg) { - uint version = _version; - int index = 0; - - while (index < _list.Count) + foreach (T item in _volatileArray) { - T item; - lock (_list) - { - if (version != _version) - { - version = _version; - index = 0; - continue; - } - - item = _list[index]; - index++; - } - - // Important to call the action outside the lock. - // This is the whole point we are having this wrapper class. action(item, arg); } } @@ -517,27 +506,8 @@ public void EnumWithExceptionNotification(Activity activity, Exception exception return; } - uint version = _version; - int index = 0; - - while (index < _list.Count) + foreach (T item in _volatileArray) { - T item; - lock (_list) - { - if (version != _version) - { - version = _version; - index = 0; - continue; - } - - item = _list[index]; - index++; - } - - // Important to notify outside the lock. - // This is the whole point we are having this wrapper class. (item as ActivityListener)!.ExceptionRecorder?.Invoke(activity, exception, ref tags); } } diff --git a/src/libraries/System.Formats.Nrbf/src/Resources/Strings.resx b/src/libraries/System.Formats.Nrbf/src/Resources/Strings.resx index 349405150c65e..6b9ffc6da372b 100644 --- a/src/libraries/System.Formats.Nrbf/src/Resources/Strings.resx +++ b/src/libraries/System.Formats.Nrbf/src/Resources/Strings.resx @@ -133,7 +133,7 @@ {0} Record Type is not supported by design. - Member reference was pointing to a record of unexpected type. + Invalid member reference. Invalid type name: `{0}`. @@ -162,4 +162,10 @@ Invalid assembly name: `{0}`. + + Invalid format. + + + A surrogate character was read. + \ No newline at end of file diff --git a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/ArraySinglePrimitiveRecord.cs b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/ArraySinglePrimitiveRecord.cs index 6b97328702bd3..ab5f68f50be82 100644 --- a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/ArraySinglePrimitiveRecord.cs +++ b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/ArraySinglePrimitiveRecord.cs @@ -171,12 +171,17 @@ private static List DecodeDecimals(BinaryReader reader, int count) reader.BaseStream.ReadExactly(buffer.Slice(0, stringLength)); - values.Add(decimal.Parse(buffer.Slice(0, stringLength), CultureInfo.InvariantCulture)); + if (!decimal.TryParse(buffer.Slice(0, stringLength), NumberStyles.Number, CultureInfo.InvariantCulture, out decimal value)) + { + ThrowHelper.ThrowInvalidFormat(); + } + + values.Add(value); } #else for (int i = 0; i < count; i++) { - values.Add(decimal.Parse(reader.ReadString(), CultureInfo.InvariantCulture)); + values.Add(reader.ParseDecimal()); } #endif return values; diff --git a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/ClassTypeInfo.cs b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/ClassTypeInfo.cs index 6a9e9d7b90afe..b0b7e543fa9b5 100644 --- a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/ClassTypeInfo.cs +++ b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/ClassTypeInfo.cs @@ -26,7 +26,7 @@ internal static ClassTypeInfo Decode(BinaryReader reader, PayloadOptions options string rawName = reader.ReadString(); SerializationRecordId libraryId = SerializationRecordId.Decode(reader); - BinaryLibraryRecord library = (BinaryLibraryRecord)recordMap[libraryId]; + BinaryLibraryRecord library = recordMap.GetRecord(libraryId); return new ClassTypeInfo(rawName.ParseNonSystemClassRecordTypeName(library, options)); } diff --git a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/ClassWithIdRecord.cs b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/ClassWithIdRecord.cs index e18033524d17e..c643d3ce8c846 100644 --- a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/ClassWithIdRecord.cs +++ b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/ClassWithIdRecord.cs @@ -34,10 +34,7 @@ internal static ClassWithIdRecord Decode( SerializationRecordId id = SerializationRecordId.Decode(reader); SerializationRecordId metadataId = SerializationRecordId.Decode(reader); - if (recordMap[metadataId] is not ClassRecord referencedRecord) - { - throw new SerializationException(SR.Serialization_InvalidReference); - } + ClassRecord referencedRecord = recordMap.GetRecord(metadataId); return new ClassWithIdRecord(id, referencedRecord); } diff --git a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/ClassWithMembersAndTypesRecord.cs b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/ClassWithMembersAndTypesRecord.cs index 117e5e90ef681..d6d8c122d3ed9 100644 --- a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/ClassWithMembersAndTypesRecord.cs +++ b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/ClassWithMembersAndTypesRecord.cs @@ -27,7 +27,7 @@ internal static ClassWithMembersAndTypesRecord Decode(BinaryReader reader, Recor MemberTypeInfo memberTypeInfo = MemberTypeInfo.Decode(reader, classInfo.MemberNames.Count, options, recordMap); SerializationRecordId libraryId = SerializationRecordId.Decode(reader); - BinaryLibraryRecord library = (BinaryLibraryRecord)recordMap[libraryId]; + BinaryLibraryRecord library = recordMap.GetRecord(libraryId); classInfo.LoadTypeName(library, options); return new ClassWithMembersAndTypesRecord(classInfo, memberTypeInfo); diff --git a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/MemberReferenceRecord.cs b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/MemberReferenceRecord.cs index 162cf0b1d5c57..14bd4e7ff1f2d 100644 --- a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/MemberReferenceRecord.cs +++ b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/MemberReferenceRecord.cs @@ -38,5 +38,5 @@ private MemberReferenceRecord(SerializationRecordId reference, RecordMap recordM internal static MemberReferenceRecord Decode(BinaryReader reader, RecordMap recordMap) => new(SerializationRecordId.Decode(reader), recordMap); - internal SerializationRecord GetReferencedRecord() => RecordMap[Reference]; + internal SerializationRecord GetReferencedRecord() => RecordMap.GetRecord(Reference); } diff --git a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/NrbfDecoder.cs b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/NrbfDecoder.cs index 6eb69eb658b9f..de4b24b6e46e1 100644 --- a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/NrbfDecoder.cs +++ b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/NrbfDecoder.cs @@ -46,6 +46,7 @@ public static bool StartsWithPayloadHeader(ReadOnlySpan bytes) /// is . /// The stream does not support reading or seeking. /// The stream was closed. + /// An I/O error occurred. /// When this method returns, is restored to its original position. public static bool StartsWithPayloadHeader(Stream stream) { @@ -107,6 +108,7 @@ public static bool StartsWithPayloadHeader(Stream stream) /// is . /// does not support reading or is already closed. /// Reading from encountered invalid NRBF data. + /// An I/O error occurred. /// /// Reading from encountered unsupported records, /// for example, arrays with non-zero offset or unsupported record types @@ -142,7 +144,14 @@ public static SerializationRecord Decode(Stream payload, out IReadOnlyDictionary #endif using BinaryReader reader = new(payload, ThrowOnInvalidUtf8Encoding, leaveOpen: leaveOpen); - return Decode(reader, options ?? new(), out recordMap); + try + { + return Decode(reader, options ?? new(), out recordMap); + } + catch (FormatException) // can be thrown by various BinaryReader methods + { + throw new SerializationException(SR.Serialization_InvalidFormat); + } } /// @@ -213,12 +222,7 @@ private static SerializationRecord Decode(BinaryReader reader, PayloadOptions op private static SerializationRecord DecodeNext(BinaryReader reader, RecordMap recordMap, AllowedRecordTypes allowed, PayloadOptions options, out SerializationRecordType recordType) { - byte nextByte = reader.ReadByte(); - if (((uint)allowed & (1u << nextByte)) == 0) - { - ThrowHelper.ThrowForUnexpectedRecordType(nextByte); - } - recordType = (SerializationRecordType)nextByte; + recordType = reader.ReadSerializationRecordType(allowed); SerializationRecord record = recordType switch { @@ -254,7 +258,7 @@ private static SerializationRecord DecodeMemberPrimitiveTypedRecord(BinaryReader PrimitiveType.Boolean => new MemberPrimitiveTypedRecord(reader.ReadBoolean()), PrimitiveType.Byte => new MemberPrimitiveTypedRecord(reader.ReadByte()), PrimitiveType.SByte => new MemberPrimitiveTypedRecord(reader.ReadSByte()), - PrimitiveType.Char => new MemberPrimitiveTypedRecord(reader.ReadChar()), + PrimitiveType.Char => new MemberPrimitiveTypedRecord(reader.ParseChar()), PrimitiveType.Int16 => new MemberPrimitiveTypedRecord(reader.ReadInt16()), PrimitiveType.UInt16 => new MemberPrimitiveTypedRecord(reader.ReadUInt16()), PrimitiveType.Int32 => new MemberPrimitiveTypedRecord(reader.ReadInt32()), @@ -263,7 +267,7 @@ private static SerializationRecord DecodeMemberPrimitiveTypedRecord(BinaryReader PrimitiveType.UInt64 => new MemberPrimitiveTypedRecord(reader.ReadUInt64()), PrimitiveType.Single => new MemberPrimitiveTypedRecord(reader.ReadSingle()), PrimitiveType.Double => new MemberPrimitiveTypedRecord(reader.ReadDouble()), - PrimitiveType.Decimal => new MemberPrimitiveTypedRecord(decimal.Parse(reader.ReadString(), CultureInfo.InvariantCulture)), + PrimitiveType.Decimal => new MemberPrimitiveTypedRecord(reader.ParseDecimal()), PrimitiveType.DateTime => new MemberPrimitiveTypedRecord(Utils.BinaryReaderExtensions.CreateDateTimeFromData(reader.ReadUInt64())), // String is handled with a record, never on it's own _ => new MemberPrimitiveTypedRecord(new TimeSpan(reader.ReadInt64())), diff --git a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/RecordMap.cs b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/RecordMap.cs index a25ab508f5db3..04a4d0e085048 100644 --- a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/RecordMap.cs +++ b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/RecordMap.cs @@ -63,7 +63,8 @@ internal void Add(SerializationRecord record) internal SerializationRecord GetRootRecord(SerializedStreamHeaderRecord header) { - SerializationRecord rootRecord = _map[header.RootId]; + SerializationRecord rootRecord = GetRecord(header.RootId); + if (rootRecord is SystemClassWithMembersAndTypesRecord systemClass) { // update the record map, so it's visible also to those who access it via Id @@ -72,4 +73,14 @@ internal SerializationRecord GetRootRecord(SerializedStreamHeaderRecord header) return rootRecord; } + + internal SerializationRecord GetRecord(SerializationRecordId recordId) + => _map.TryGetValue(recordId, out SerializationRecord? record) + ? record + : throw new SerializationException(SR.Serialization_InvalidReference); + + internal T GetRecord(SerializationRecordId recordId) where T : SerializationRecord + => _map.TryGetValue(recordId, out SerializationRecord? record) && record is T casted + ? casted + : throw new SerializationException(SR.Serialization_InvalidReference); } diff --git a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/Utils/BinaryReaderExtensions.cs b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/Utils/BinaryReaderExtensions.cs index 5cd81be6d9995..cd705223021fc 100644 --- a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/Utils/BinaryReaderExtensions.cs +++ b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/Utils/BinaryReaderExtensions.cs @@ -15,6 +15,19 @@ internal static class BinaryReaderExtensions { private static object? s_baseAmbiguousDstDateTime; + internal static SerializationRecordType ReadSerializationRecordType(this BinaryReader reader, AllowedRecordTypes allowed) + { + byte nextByte = reader.ReadByte(); + if (nextByte > (byte)SerializationRecordType.MethodReturn // MethodReturn is the last defined value. + || (nextByte > (byte)SerializationRecordType.ArraySingleString && nextByte < (byte)SerializationRecordType.MethodCall) // not part of the spec + || ((uint)allowed & (1u << nextByte)) == 0) // valid, but not allowed + { + ThrowHelper.ThrowForUnexpectedRecordType(nextByte); + } + + return (SerializationRecordType)nextByte; + } + internal static BinaryArrayType ReadArrayType(this BinaryReader reader) { byte arrayType = reader.ReadByte(); @@ -48,7 +61,7 @@ internal static PrimitiveType ReadPrimitiveType(this BinaryReader reader) { byte primitiveType = reader.ReadByte(); // String is the last defined value, 4 is not used at all. - if (primitiveType is 4 or > (byte)PrimitiveType.String) + if (primitiveType is 0 or 4 or (byte)PrimitiveType.Null or > (byte)PrimitiveType.String) { ThrowHelper.ThrowInvalidValue(primitiveType); } @@ -64,7 +77,7 @@ internal static object ReadPrimitiveValue(this BinaryReader reader, PrimitiveTyp PrimitiveType.Boolean => reader.ReadBoolean(), PrimitiveType.Byte => reader.ReadByte(), PrimitiveType.SByte => reader.ReadSByte(), - PrimitiveType.Char => reader.ReadChar(), + PrimitiveType.Char => reader.ParseChar(), PrimitiveType.Int16 => reader.ReadInt16(), PrimitiveType.UInt16 => reader.ReadUInt16(), PrimitiveType.Int32 => reader.ReadInt32(), @@ -73,11 +86,35 @@ internal static object ReadPrimitiveValue(this BinaryReader reader, PrimitiveTyp PrimitiveType.UInt64 => reader.ReadUInt64(), PrimitiveType.Single => reader.ReadSingle(), PrimitiveType.Double => reader.ReadDouble(), - PrimitiveType.Decimal => decimal.Parse(reader.ReadString(), CultureInfo.InvariantCulture), + PrimitiveType.Decimal => reader.ParseDecimal(), PrimitiveType.DateTime => CreateDateTimeFromData(reader.ReadUInt64()), _ => new TimeSpan(reader.ReadInt64()), }; + // BinaryFormatter serializes decimals as strings and we can't BinaryReader.ReadDecimal. + internal static decimal ParseDecimal(this BinaryReader reader) + { + string text = reader.ReadString(); + if (!decimal.TryParse(text, NumberStyles.Number, CultureInfo.InvariantCulture, out decimal result)) + { + ThrowHelper.ThrowInvalidFormat(); + } + + return result; + } + + internal static char ParseChar(this BinaryReader reader) + { + try + { + return reader.ReadChar(); + } + catch (ArgumentException) // A surrogate character was read. + { + throw new SerializationException(SR.Serialization_SurrogateCharacter); + } + } + /// /// Creates a object from raw data with validation. /// diff --git a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/Utils/ThrowHelper.cs b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/Utils/ThrowHelper.cs index f096bfc736098..55febf77533f9 100644 --- a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/Utils/ThrowHelper.cs +++ b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/Utils/ThrowHelper.cs @@ -29,6 +29,9 @@ internal static void ThrowArrayContainedNulls() internal static void ThrowInvalidAssemblyName(string rawName) => throw new SerializationException(SR.Format(SR.Serialization_InvalidAssemblyName, rawName)); + internal static void ThrowInvalidFormat() + => throw new SerializationException(SR.Serialization_InvalidFormat); + internal static void ThrowEndOfStreamException() => throw new EndOfStreamException(); diff --git a/src/libraries/System.Formats.Nrbf/tests/InvalidInputTests.cs b/src/libraries/System.Formats.Nrbf/tests/InvalidInputTests.cs index bc134350eb7c9..b1625c7ca9287 100644 --- a/src/libraries/System.Formats.Nrbf/tests/InvalidInputTests.cs +++ b/src/libraries/System.Formats.Nrbf/tests/InvalidInputTests.cs @@ -426,7 +426,9 @@ public static IEnumerable ThrowsForInvalidPrimitiveType_Arguments() { foreach (byte binaryType in new byte[] { (byte)0 /* BinaryType.Primitive */, (byte)7 /* BinaryType.PrimitiveArray */ }) { + yield return new object[] { recordType, binaryType, (byte)0 }; // value not used by the spec yield return new object[] { recordType, binaryType, (byte)4 }; // value not used by the spec + yield return new object[] { recordType, binaryType, (byte)17 }; // used by the spec, but illegal in given context yield return new object[] { recordType, binaryType, (byte)19 }; } } @@ -478,4 +480,109 @@ public void ThrowsOnInvalidArrayType() stream.Position = 0; Assert.Throws(() => NrbfDecoder.Decode(stream)); } + + [Theory] + [InlineData(18, typeof(NotSupportedException))] // not part of the spec, but still less than max allowed value (22) + [InlineData(19, typeof(NotSupportedException))] // same as above + [InlineData(20, typeof(NotSupportedException))] // same as above + [InlineData(23, typeof(SerializationException))] // not part of the spec and more than max allowed value (22) + [InlineData(64, typeof(SerializationException))] // same as above but also matches AllowedRecordTypes.SerializedStreamHeader + public void InvalidSerializationRecordType(byte recordType, Type expectedException) + { + using MemoryStream stream = new(); + BinaryWriter writer = new(stream, Encoding.UTF8); + + WriteSerializedStreamHeader(writer); + writer.Write(recordType); // SerializationRecordType + writer.Write((byte)SerializationRecordType.MessageEnd); + + stream.Position = 0; + + Assert.Throws(expectedException, () => NrbfDecoder.Decode(stream)); + } + + [Fact] + public void MissingRootRecord() + { + const int RootRecordId = 1; + using MemoryStream stream = new(); + BinaryWriter writer = new(stream, Encoding.UTF8); + + WriteSerializedStreamHeader(writer, rootId: RootRecordId); + writer.Write((byte)SerializationRecordType.BinaryObjectString); + writer.Write(RootRecordId + 1); // a different ID + writer.Write("theString"); + writer.Write((byte)SerializationRecordType.MessageEnd); + + stream.Position = 0; + + Assert.Throws(() => NrbfDecoder.Decode(stream)); + } + + [Fact] + public void Invalid7BitEncodedStringLength() + { + // The highest bit of the last byte is set (so it's invalid). + byte[] invalidLength = [byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue]; + + using MemoryStream stream = new(); + BinaryWriter writer = new(stream, Encoding.UTF8); + + WriteSerializedStreamHeader(writer); + writer.Write((byte)SerializationRecordType.BinaryObjectString); + writer.Write(1); // root record Id + writer.Write(invalidLength); // the length prefix + writer.Write(Encoding.UTF8.GetBytes("theString")); + writer.Write((byte)SerializationRecordType.MessageEnd); + + stream.Position = 0; + + Assert.Throws(() => NrbfDecoder.Decode(stream)); + } + + [Theory] + [InlineData("79228162514264337593543950336")] // invalid format (decimal.MaxValue + 1) + [InlineData("1111111111111111111111111111111111111111111111111")] // overflow + public void InvalidDecimal(string textRepresentation) + { + using MemoryStream stream = new(); + BinaryWriter writer = new(stream, Encoding.UTF8); + + WriteSerializedStreamHeader(writer); + writer.Write((byte)SerializationRecordType.SystemClassWithMembersAndTypes); + writer.Write(1); // root record Id + writer.Write("ClassWithDecimalField"); // type name + writer.Write(1); // member count + writer.Write("memberName"); + writer.Write((byte)BinaryType.Primitive); + writer.Write((byte)PrimitiveType.Decimal); + writer.Write(textRepresentation); + writer.Write((byte)SerializationRecordType.MessageEnd); + + stream.Position = 0; + + Assert.Throws(() => NrbfDecoder.Decode(stream)); + } + + [Fact] + public void SurrogateCharacter() + { + using MemoryStream stream = new(); + BinaryWriter writer = new(stream, Encoding.UTF8); + + WriteSerializedStreamHeader(writer); + writer.Write((byte)SerializationRecordType.SystemClassWithMembersAndTypes); + writer.Write(1); // root record Id + writer.Write("ClassWithCharField"); // type name + writer.Write(1); // member count + writer.Write("memberName"); + writer.Write((byte)BinaryType.Primitive); + writer.Write((byte)PrimitiveType.Char); + writer.Write((byte)0xC0); // a surrogate character + writer.Write((byte)SerializationRecordType.MessageEnd); + + stream.Position = 0; + + Assert.Throws(() => NrbfDecoder.Decode(stream)); + } } diff --git a/src/libraries/System.Formats.Nrbf/tests/ReadTests.cs b/src/libraries/System.Formats.Nrbf/tests/ReadTests.cs index b9bee7d881a69..0c7bd2045fa1f 100644 --- a/src/libraries/System.Formats.Nrbf/tests/ReadTests.cs +++ b/src/libraries/System.Formats.Nrbf/tests/ReadTests.cs @@ -45,10 +45,10 @@ protected static BinaryFormatter CreateBinaryFormatter() }; #pragma warning restore SYSLIB0011 // Type or member is obsolete - protected static void WriteSerializedStreamHeader(BinaryWriter writer, int major = 1, int minor = 0) + protected static void WriteSerializedStreamHeader(BinaryWriter writer, int major = 1, int minor = 0, int rootId = 1) { writer.Write((byte)SerializationRecordType.SerializedStreamHeader); - writer.Write(1); // root ID + writer.Write(rootId); // root ID writer.Write(1); // header ID writer.Write(major); // major version writer.Write(minor); // minor version diff --git a/src/libraries/System.Formats.Nrbf/tests/System.Formats.Nrbf.Tests.csproj b/src/libraries/System.Formats.Nrbf/tests/System.Formats.Nrbf.Tests.csproj index a9da043b5ecd5..c31537bb983ef 100644 --- a/src/libraries/System.Formats.Nrbf/tests/System.Formats.Nrbf.Tests.csproj +++ b/src/libraries/System.Formats.Nrbf/tests/System.Formats.Nrbf.Tests.csproj @@ -7,6 +7,8 @@ + + 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/Internal/Runtime/InteropServices/ComponentActivator.cs b/src/libraries/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComponentActivator.cs index 7634a76f42940..dee00844a55c7 100644 --- a/src/libraries/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComponentActivator.cs +++ b/src/libraries/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComponentActivator.cs @@ -67,6 +67,9 @@ public static unsafe int LoadAssemblyAndGetFunctionPointer(IntPtr assemblyPathNa IntPtr reserved, IntPtr functionHandle) { + if (functionHandle != IntPtr.Zero) + *(IntPtr*)functionHandle = 0; + if (!IsSupported) return HostFeatureDisabled; @@ -229,6 +232,9 @@ public static unsafe int GetFunctionPointer(IntPtr typeNameNative, IntPtr reserved, IntPtr functionHandle) { + if (functionHandle != IntPtr.Zero) + *(IntPtr*)functionHandle = 0; + if (!IsSupported) { #if CORECLR 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.Runtime.Serialization.Formatters/System.Runtime.Serialization.Formatters.sln b/src/libraries/System.Runtime.Serialization.Formatters/System.Runtime.Serialization.Formatters.sln index 62233f1d02a41..03d2d3913f147 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/System.Runtime.Serialization.Formatters.sln +++ b/src/libraries/System.Runtime.Serialization.Formatters/System.Runtime.Serialization.Formatters.sln @@ -147,6 +147,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ref", "tools\ref", "{CDD725 EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{21D78340-7F96-4519-983F-529077A11AE1}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Runtime.Serialization.Formatters.Disabled.Tests", "tests\Disabled\System.Runtime.Serialization.Formatters.Disabled.Tests.csproj", "{0C8ADEFB-33FB-4785-A828-93377745B2BA}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1561,6 +1563,36 @@ Global {5149AC24-C1A7-4A4C-BE83-FF3037B99E4C}.Checked|arm64.ActiveCfg = Debug|Any CPU {5149AC24-C1A7-4A4C-BE83-FF3037B99E4C}.Checked|x64.ActiveCfg = Debug|Any CPU {5149AC24-C1A7-4A4C-BE83-FF3037B99E4C}.Checked|x86.ActiveCfg = Debug|Any CPU + {0C8ADEFB-33FB-4785-A828-93377745B2BA}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {0C8ADEFB-33FB-4785-A828-93377745B2BA}.Checked|Any CPU.Build.0 = Debug|Any CPU + {0C8ADEFB-33FB-4785-A828-93377745B2BA}.Checked|arm.ActiveCfg = Debug|Any CPU + {0C8ADEFB-33FB-4785-A828-93377745B2BA}.Checked|arm.Build.0 = Debug|Any CPU + {0C8ADEFB-33FB-4785-A828-93377745B2BA}.Checked|arm64.ActiveCfg = Debug|Any CPU + {0C8ADEFB-33FB-4785-A828-93377745B2BA}.Checked|arm64.Build.0 = Debug|Any CPU + {0C8ADEFB-33FB-4785-A828-93377745B2BA}.Checked|x64.ActiveCfg = Debug|Any CPU + {0C8ADEFB-33FB-4785-A828-93377745B2BA}.Checked|x64.Build.0 = Debug|Any CPU + {0C8ADEFB-33FB-4785-A828-93377745B2BA}.Checked|x86.ActiveCfg = Debug|Any CPU + {0C8ADEFB-33FB-4785-A828-93377745B2BA}.Checked|x86.Build.0 = Debug|Any CPU + {0C8ADEFB-33FB-4785-A828-93377745B2BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0C8ADEFB-33FB-4785-A828-93377745B2BA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0C8ADEFB-33FB-4785-A828-93377745B2BA}.Debug|arm.ActiveCfg = Debug|Any CPU + {0C8ADEFB-33FB-4785-A828-93377745B2BA}.Debug|arm.Build.0 = Debug|Any CPU + {0C8ADEFB-33FB-4785-A828-93377745B2BA}.Debug|arm64.ActiveCfg = Debug|Any CPU + {0C8ADEFB-33FB-4785-A828-93377745B2BA}.Debug|arm64.Build.0 = Debug|Any CPU + {0C8ADEFB-33FB-4785-A828-93377745B2BA}.Debug|x64.ActiveCfg = Debug|Any CPU + {0C8ADEFB-33FB-4785-A828-93377745B2BA}.Debug|x64.Build.0 = Debug|Any CPU + {0C8ADEFB-33FB-4785-A828-93377745B2BA}.Debug|x86.ActiveCfg = Debug|Any CPU + {0C8ADEFB-33FB-4785-A828-93377745B2BA}.Debug|x86.Build.0 = Debug|Any CPU + {0C8ADEFB-33FB-4785-A828-93377745B2BA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0C8ADEFB-33FB-4785-A828-93377745B2BA}.Release|Any CPU.Build.0 = Release|Any CPU + {0C8ADEFB-33FB-4785-A828-93377745B2BA}.Release|arm.ActiveCfg = Release|Any CPU + {0C8ADEFB-33FB-4785-A828-93377745B2BA}.Release|arm.Build.0 = Release|Any CPU + {0C8ADEFB-33FB-4785-A828-93377745B2BA}.Release|arm64.ActiveCfg = Release|Any CPU + {0C8ADEFB-33FB-4785-A828-93377745B2BA}.Release|arm64.Build.0 = Release|Any CPU + {0C8ADEFB-33FB-4785-A828-93377745B2BA}.Release|x64.ActiveCfg = Release|Any CPU + {0C8ADEFB-33FB-4785-A828-93377745B2BA}.Release|x64.Build.0 = Release|Any CPU + {0C8ADEFB-33FB-4785-A828-93377745B2BA}.Release|x86.ActiveCfg = Release|Any CPU + {0C8ADEFB-33FB-4785-A828-93377745B2BA}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1635,6 +1667,7 @@ Global {E8705420-F755-4CBA-970D-B745F59F9780} = {21D78340-7F96-4519-983F-529077A11AE1} {5149AC24-C1A7-4A4C-BE83-FF3037B99E4C} = {CDD72541-F0ED-41FA-9C9A-5D774CEB22E4} {CDD72541-F0ED-41FA-9C9A-5D774CEB22E4} = {21D78340-7F96-4519-983F-529077A11AE1} + {0C8ADEFB-33FB-4785-A828-93377745B2BA} = {F8CB1B1F-F935-4ECE-B3C2-CF62B5654BF2} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {158060A0-BFF9-48E6-90A9-93F52FEB5D3B} diff --git a/src/libraries/System.Runtime.Serialization.Formatters/tests/DisableBitTests.cs b/src/libraries/System.Runtime.Serialization.Formatters/tests/Disabled/DisableBitTests.cs similarity index 100% rename from src/libraries/System.Runtime.Serialization.Formatters/tests/DisableBitTests.cs rename to src/libraries/System.Runtime.Serialization.Formatters/tests/Disabled/DisableBitTests.cs diff --git a/src/libraries/System.Runtime.Serialization.Formatters/tests/Disabled/System.Runtime.Serialization.Formatters.Disabled.Tests.csproj b/src/libraries/System.Runtime.Serialization.Formatters/tests/Disabled/System.Runtime.Serialization.Formatters.Disabled.Tests.csproj new file mode 100644 index 0000000000000..8ea7a29a3930b --- /dev/null +++ b/src/libraries/System.Runtime.Serialization.Formatters/tests/Disabled/System.Runtime.Serialization.Formatters.Disabled.Tests.csproj @@ -0,0 +1,23 @@ + + + true + true + $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-freebsd;$(NetCoreAppCurrent)-illumos;$(NetCoreAppCurrent)-solaris;$(NetCoreAppCurrent)-haiku;$(NetCoreAppCurrent)-linux;$(NetCoreAppCurrent)-osx;$(NetCoreAppCurrent)-ios;$(NetCoreAppCurrent)-tvos + + + + + + + + + + + + + diff --git a/src/libraries/System.Runtime.Serialization.Formatters/tests/SerializationGuardTests.cs b/src/libraries/System.Runtime.Serialization.Formatters/tests/SerializationGuardTests.cs index 3805070b47d8e..444e0cc2f3856 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/tests/SerializationGuardTests.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/tests/SerializationGuardTests.cs @@ -1,125 +1,40 @@ // 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.Diagnostics; using System.IO; -using System.Reflection; using System.Runtime.Serialization.Formatters.Binary; -using System.Threading; -using System.Threading.Tasks; using Xunit; namespace System.Runtime.Serialization.Formatters.Tests { + // When BinaryFormatter was built-in to the platform we used to activate SerializationGuard in ObjectReader.Deserialize, + // but now that it has moved to an OOB offering it no longer does. [ConditionalClass(typeof(TestConfiguration), nameof(TestConfiguration.IsBinaryFormatterEnabled))] public static class SerializationGuardTests { [Fact] - public static void BlockAssemblyLoads() - { - TryPayload(new AssemblyLoader()); - } - - [Fact] - public static void BlockProcessStarts() - { - TryPayload(new ProcessStarter()); - } - - [Fact] - public static void BlockFileWrites() - { - TryPayload(new FileWriter()); - } - - [Fact] - public static void BlockAsyncDodging() - { - TryPayload(new AsyncDodger()); - } - - private static void TryPayload(object payload) + public static void IsNoLongerActivated() { MemoryStream ms = new MemoryStream(); BinaryFormatter writer = new BinaryFormatter(); - writer.Serialize(ms, payload); + writer.Serialize(ms, new ThrowIfDeserializationInProgress()); ms.Position = 0; BinaryFormatter reader = new BinaryFormatter(); - SerializationException se = Assert.Throws(() => reader.Deserialize(ms)); - Assert.IsAssignableFrom(se.InnerException); - } - } - - [Serializable] - internal class AssemblyLoader : ISerializable - { - public AssemblyLoader() { } - - public AssemblyLoader(SerializationInfo info, StreamingContext context) - { - Assembly.Load(new byte[1000]); - } - - public void GetObjectData(SerializationInfo info, StreamingContext context) - { + Assert.NotNull(reader.Deserialize(ms)); } } [Serializable] - internal class ProcessStarter : ISerializable + internal class ThrowIfDeserializationInProgress : ISerializable { - public ProcessStarter() { } - - private ProcessStarter(SerializationInfo info, StreamingContext context) - { - Process.Start("calc.exe"); - } + private static int s_cachedSerializationSwitch; - public void GetObjectData(SerializationInfo info, StreamingContext context) - { - } - } - - [Serializable] - internal class FileWriter : ISerializable - { - public FileWriter() { } - - private FileWriter(SerializationInfo info, StreamingContext context) - { - string tempPath = Path.GetTempFileName(); - File.WriteAllText(tempPath, "This better not be written..."); - throw new UnreachableException("Unreachable code (SerializationGuard should have kicked in)"); - } - - public void GetObjectData(SerializationInfo info, StreamingContext context) - { - } - } - - [Serializable] - internal class AsyncDodger : ISerializable - { - public AsyncDodger() { } - - private AsyncDodger(SerializationInfo info, StreamingContext context) - { - try - { - Task t = Task.Factory.StartNew(LoadAssemblyOnBackgroundThread, TaskCreationOptions.LongRunning); - t.Wait(); - } - catch (AggregateException ex) - { - throw ex.InnerException; - } - } + public ThrowIfDeserializationInProgress() { } - private void LoadAssemblyOnBackgroundThread() + private ThrowIfDeserializationInProgress(SerializationInfo info, StreamingContext context) { - Assembly.Load(new byte[1000]); + SerializationGuard.ThrowIfDeserializationInProgress("AllowProcessCreation", ref s_cachedSerializationSwitch); } public void GetObjectData(SerializationInfo info, StreamingContext context) diff --git a/src/libraries/System.Runtime.Serialization.Formatters/tests/System.Runtime.Serialization.Formatters.Tests.csproj b/src/libraries/System.Runtime.Serialization.Formatters/tests/System.Runtime.Serialization.Formatters.Tests.csproj index 03df94a257abd..96a0f784a2372 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/tests/System.Runtime.Serialization.Formatters.Tests.csproj +++ b/src/libraries/System.Runtime.Serialization.Formatters/tests/System.Runtime.Serialization.Formatters.Tests.csproj @@ -7,7 +7,6 @@ - @@ -36,6 +35,8 @@ + @@ -48,8 +49,11 @@ - + + @@ -65,15 +69,4 @@ - - - - - - diff --git a/src/mono/browser/runtime/jiterpreter-enums.ts b/src/mono/browser/runtime/jiterpreter-enums.ts index b65315ec4cf9b..3caa16bb61349 100644 --- a/src/mono/browser/runtime/jiterpreter-enums.ts +++ b/src/mono/browser/runtime/jiterpreter-enums.ts @@ -21,6 +21,8 @@ export const enum JiterpCounter { BackBranchesNotEmitted, ElapsedGenerationMs, ElapsedCompilationMs, + SwitchTargetsOk, + SwitchTargetsFailed, } // keep in sync with jiterpreter.c, see mono_jiterp_get_member_offset @@ -127,7 +129,8 @@ export const enum BailoutReason { Icall, UnexpectedRetIp, LeaveCheck, - Switch, + SwitchSize, + SwitchTarget, } export const BailoutReasonNames = [ @@ -158,7 +161,8 @@ export const BailoutReasonNames = [ "Icall", "UnexpectedRetIp", "LeaveCheck", - "Switch", + "SwitchSize", + "SwitchTarget", ]; export const enum JitQueue { 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-support.ts b/src/mono/browser/runtime/jiterpreter-support.ts index 3ba0a3c6db506..6fe9453662fff 100644 --- a/src/mono/browser/runtime/jiterpreter-support.ts +++ b/src/mono/browser/runtime/jiterpreter-support.ts @@ -1150,7 +1150,14 @@ type CfgBranch = { branchType: CfgBranchType; } -type CfgSegment = CfgBlob | CfgBranchBlockHeader | CfgBranch; +type CfgJumpTable = { + type: "jump-table"; + from: MintOpcodePtr; + targets: MintOpcodePtr[]; + fallthrough: MintOpcodePtr; +} + +type CfgSegment = CfgBlob | CfgBranchBlockHeader | CfgBranch | CfgJumpTable; export const enum CfgBranchType { Unconditional, @@ -1278,6 +1285,23 @@ class Cfg { } } + // It's the caller's responsibility to wrap this in a block and follow it with a bailout! + jumpTable (targets: MintOpcodePtr[], fallthrough: MintOpcodePtr) { + this.appendBlob(); + this.segments.push({ + type: "jump-table", + from: this.ip, + targets, + fallthrough, + }); + // opcode, length, fallthrough (approximate) + this.overheadBytes += 4; + // length of branch depths (approximate) + this.overheadBytes += targets.length; + // bailout for missing targets (approximate) + this.overheadBytes += 24; + } + emitBlob (segment: CfgBlob, source: Uint8Array) { // mono_log_info(`segment @${(segment.ip).toString(16)} ${segment.start}-${segment.start + segment.length}`); const view = source.subarray(segment.start, segment.start + segment.length); @@ -1415,6 +1439,38 @@ class Cfg { this.blockStack.shift(); break; } + case "jump-table": { + // Our caller wrapped us in a block and put a missing target bailout after us + const offset = 1; + // The selector was already loaded onto the wasm stack before cfg.jumpTable was called, + // so we just need to generate a br_table + this.builder.appendU8(WasmOpcode.br_table); + this.builder.appendULeb(segment.targets.length); + for (const target of segment.targets) { + const indexInStack = this.blockStack.indexOf(target); + if (indexInStack >= 0) { + modifyCounter(JiterpCounter.SwitchTargetsOk, 1); + this.builder.appendULeb(indexInStack + offset); + } else { + modifyCounter(JiterpCounter.SwitchTargetsFailed, 1); + if (this.trace > 0) + mono_log_info(`Switch target ${target} not found in block stack ${this.blockStack}`); + this.builder.appendULeb(0); + } + } + const fallthroughIndex = this.blockStack.indexOf(segment.fallthrough); + if (fallthroughIndex >= 0) { + modifyCounter(JiterpCounter.SwitchTargetsOk, 1); + this.builder.appendULeb(fallthroughIndex + offset); + } else { + modifyCounter(JiterpCounter.SwitchTargetsFailed, 1); + if (this.trace > 0) + mono_log_info(`Switch fallthrough ${segment.fallthrough} not found in block stack ${this.blockStack}`); + this.builder.appendULeb(0); + } + this.builder.appendU8(WasmOpcode.unreachable); + break; + } case "branch": { const lookupTarget = segment.isBackward ? dispatchIp : segment.target; let indexInStack = this.blockStack.indexOf(lookupTarget), @@ -1965,6 +2021,7 @@ export type JiterpreterOptions = { tableSize: number; aotTableSize: number; maxModuleSize: number; + maxSwitchSize: number; } const optionNames: { [jsName: string]: string } = { @@ -2002,6 +2059,7 @@ const optionNames: { [jsName: string]: string } = { "tableSize": "jiterpreter-table-size", "aotTableSize": "jiterpreter-aot-table-size", "maxModuleSize": "jiterpreter-max-module-size", + "maxSwitchSize": "jiterpreter-max-switch-size", }; let optionsVersion = -1; diff --git a/src/mono/browser/runtime/jiterpreter-trace-generator.ts b/src/mono/browser/runtime/jiterpreter-trace-generator.ts index 9ca8453e58a8c..8d88b2ff98e42 100644 --- a/src/mono/browser/runtime/jiterpreter-trace-generator.ts +++ b/src/mono/browser/runtime/jiterpreter-trace-generator.ts @@ -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. +import WasmEnableThreads from "consts:wasmEnableThreads"; import { MonoMethod } from "./types/internal"; import { NativePointer } from "./types/emscripten"; import { @@ -9,7 +10,7 @@ import { } from "./memory"; import { WasmOpcode, WasmSimdOpcode, WasmValtype, - getOpcodeName, MintOpArgType + getOpcodeName, MintOpArgType, WasmAtomicOpcode } from "./jiterpreter-opcodes"; import { MintOpcode, SimdInfo, @@ -183,6 +184,34 @@ function getOpcodeLengthU16 (ip: MintOpcodePtr, opcode: MintOpcode) { } } +function decodeSwitch (ip: MintOpcodePtr) : MintOpcodePtr[] { + mono_assert(getU16(ip) === MintOpcode.MINT_SWITCH, "decodeSwitch called on a non-switch"); + const n = getArgU32(ip, 2); + const result = []; + /* + guint32 val = LOCAL_VAR (ip [1], guint32); + guint32 n = READ32 (ip + 2); + ip += 4; + if (val < n) { + ip += 2 * val; + int offset = READ32 (ip); + ip += offset; + } else { + ip += 2 * n; + } + */ + // mono_log_info(`switch[${n}] @${ip}`); + for (let i = 0; i < n; i++) { + const base = ip + 8 + (4 * i), + offset = getU32_unaligned(base), + target = base + (offset * 2); + // mono_log_info(` ${i} -> ${target}`); + result.push(target); + } + + return result; +} + // Perform a quick scan through the opcodes potentially in this trace to build a table of // backwards branch targets, compatible with the layout of the old one that was generated in C. // We do this here to match the exact way that the jiterp calculates branch targets, since @@ -204,47 +233,60 @@ export function generateBackwardBranchTable ( const opcode = getU16(ip); const opLengthU16 = getOpcodeLengthU16(ip, opcode); - // Any opcode with a branch argtype will have a decoded displacement, even if we don't - // implement the opcode. Everything else will return undefined here and be skipped - const displacement = getBranchDisplacement(ip, opcode); - if (typeof (displacement) !== "number") { - ip += (opLengthU16 * 2); - continue; - } - - // These checks shouldn't fail unless memory is corrupted or something is wrong with the decoder. - // We don't want to cause decoder bugs to make the application exit, though - graceful degradation. - if (displacement === 0) { - mono_log_info(`opcode @${ip} branch target is self. aborting backbranch table generation`); - break; - } + if (opcode === MintOpcode.MINT_SWITCH) { + // FIXME: Once the cfg supports back-branches in jump tables, uncomment this to + // insert the back-branch targets into the table so they'll actually work + /* + const switchTable = decodeSwitch(ip); + for (const target of switchTable) { + const rtarget16 = (target - startOfBody) / 2; + if (target < ip) + table.push(rtarget16); + } + */ + } else { + // Any opcode with a branch argtype will have a decoded displacement, even if we don't + // implement the opcode. Everything else will return undefined here and be skipped + const displacement = getBranchDisplacement(ip, opcode); + if (typeof (displacement) !== "number") { + ip += (opLengthU16 * 2); + continue; + } - // Only record *backward* branches - // We will filter this down further in the Cfg because it takes note of which branches it sees, - // but it is also beneficial to have a null table (further down) due to seeing no potential - // back branch targets at all, as it allows the Cfg to skip additional code generation entirely - // if it knows there will never be any backwards branches in a given trace - if (displacement < 0) { - const rtarget16 = rip16 + (displacement); - if (rtarget16 < 0) { - mono_log_info(`opcode @${ip}'s displacement of ${displacement} goes before body: ${rtarget16}. aborting backbranch table generation`); + // These checks shouldn't fail unless memory is corrupted or something is wrong with the decoder. + // We don't want to cause decoder bugs to make the application exit, though - graceful degradation. + if (displacement === 0) { + mono_log_info(`opcode @${ip} branch target is self. aborting backbranch table generation`); break; } - // If the relative target is before the start of the trace, don't record it. - // The trace will be unable to successfully branch to it so it would just make the table bigger. - if (rtarget16 >= rbase16) - table.push(rtarget16); - } + // Only record *backward* branches + // We will filter this down further in the Cfg because it takes note of which branches it sees, + // but it is also beneficial to have a null table (further down) due to seeing no potential + // back branch targets at all, as it allows the Cfg to skip additional code generation entirely + // if it knows there will never be any backwards branches in a given trace + if (displacement < 0) { + const rtarget16 = rip16 + (displacement); + if (rtarget16 < 0) { + mono_log_info(`opcode @${ip}'s displacement of ${displacement} goes before body: ${rtarget16}. aborting backbranch table generation`); + break; + } - switch (opcode) { - case MintOpcode.MINT_CALL_HANDLER: - case MintOpcode.MINT_CALL_HANDLER_S: - // While this formally isn't a backward branch target, we want to record - // the offset of its following instruction so that the jiterpreter knows - // to generate the necessary dispatch code to enable branching back to it. - table.push(rip16 + opLengthU16); - break; + // If the relative target is before the start of the trace, don't record it. + // The trace will be unable to successfully branch to it so it would just make the table bigger. + if (rtarget16 >= rbase16) + table.push(rtarget16); + } + + switch (opcode) { + case MintOpcode.MINT_CALL_HANDLER: + case MintOpcode.MINT_CALL_HANDLER_S: + // While this formally isn't a backward branch target, we want to record + // the offset of its following instruction so that the jiterpreter knows + // to generate the necessary dispatch code to enable branching back to it. + table.push(rip16 + opLengthU16); + break; + } } ip += (opLengthU16 * 2); @@ -398,7 +440,7 @@ export function generateWasmBody ( switch (opcode) { case MintOpcode.MINT_SWITCH: { - if (!emit_switch(builder, ip)) + if (!emit_switch(builder, ip, exitOpcodeCounter)) ip = abort; break; } @@ -1238,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)); @@ -3484,19 +3541,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 @@ -3515,7 +3559,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)) @@ -3535,7 +3579,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); @@ -3975,6 +4019,20 @@ function emit_simd_4 (builder: WasmBuilder, ip: MintOpcodePtr, index: SimdIntrin function emit_atomics ( builder: WasmBuilder, ip: MintOpcodePtr, opcode: number ) { + if (opcode === MintOpcode.MINT_MONO_MEMORY_BARRIER) { + if (WasmEnableThreads) { + // Mono memory barriers use sync_synchronize which generates atomic.fence on clang, + // provided you pass -pthread at compile time + builder.appendAtomic(WasmAtomicOpcode.atomic_fence); + // The text format and other parts of the spec say atomic.fence has no operands, + // but the binary encoding contains a byte specifying whether the barrier is + // sequentially consistent (0) or acquire-release (1) + // Mono memory barriers are sync_synchronize which is sequentially consistent. + builder.appendU8(0); + } + return true; + } + if (!builder.options.enableAtomics) return false; @@ -4021,7 +4079,39 @@ function emit_atomics ( return false; } -function emit_switch (builder: WasmBuilder, ip: MintOpcodePtr) : boolean { - append_bailout(builder, ip, BailoutReason.Switch); +function emit_switch (builder: WasmBuilder, ip: MintOpcodePtr, exitOpcodeCounter: number) : boolean { + const lengthU16 = getOpcodeLengthU16(ip, MintOpcode.MINT_SWITCH), + table = decodeSwitch(ip); + let failed = false; + + if (table.length > builder.options.maxSwitchSize) { + failed = true; + } else { + // Record all the switch's forward branch targets. + // If it contains any back branches they will bailout at runtime. + for (const target of table) { + if (target > ip) + builder.branchTargets.add(target); + } + } + + if (failed) { + modifyCounter(JiterpCounter.SwitchTargetsFailed, table.length); + append_bailout(builder, ip, BailoutReason.SwitchSize); + return true; + } + + const fallthrough = ip + (lengthU16 * 2); + builder.branchTargets.add(fallthrough); + + // Jump table needs a block so it can `br 0` for missing targets + builder.block(); + // Load selector + append_ldloc(builder, getArgU16(ip, 1), WasmOpcode.i32_load); + // Dispatch + builder.cfg.jumpTable(table, fallthrough); + // Missing target + builder.endBlock(); + append_exit(builder, ip, exitOpcodeCounter, BailoutReason.SwitchTarget); return true; } diff --git a/src/mono/browser/runtime/jiterpreter.ts b/src/mono/browser/runtime/jiterpreter.ts index 68130b681358a..7aab49e6bf266 100644 --- a/src/mono/browser/runtime/jiterpreter.ts +++ b/src/mono/browser/runtime/jiterpreter.ts @@ -79,6 +79,7 @@ export const callTargetCounts: { [method: number]: number } = {}; export let mostRecentTrace: InstrumentedTraceState | undefined; export let mostRecentOptions: JiterpreterOptions | undefined = undefined; +export let traceTableIsFull = false; // You can disable an opcode for debugging purposes by adding it to this list, // instead of aborting the trace it will insert a bailout instead. This means that you will @@ -271,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")), @@ -464,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", { @@ -861,6 +872,11 @@ function generate_wasm ( idx = presetFunctionPointer; } else { idx = addWasmFunctionPointer(JiterpreterTable.Trace, fn); + if (idx === 0) { + // Failed to add function pointer because trace table is full. Disable future + // trace generation to reduce CPU usage. + traceTableIsFull = true; + } } if (trace >= 2) mono_log_info(`${traceName} -> fn index ${idx}`); @@ -984,6 +1000,8 @@ export function mono_interp_tier_prepare_jiterpreter ( return JITERPRETER_NOT_JITTED; else if (mostRecentOptions.wasmBytesLimit <= getCounter(JiterpCounter.BytesGenerated)) return JITERPRETER_NOT_JITTED; + else if (traceTableIsFull) + return JITERPRETER_NOT_JITTED; let info = traceInfo[index]; @@ -1078,7 +1096,9 @@ export function jiterpreter_dump_stats (concise?: boolean): void { traceCandidates = getCounter(JiterpCounter.TraceCandidates), bytesGenerated = getCounter(JiterpCounter.BytesGenerated), elapsedGenerationMs = getCounter(JiterpCounter.ElapsedGenerationMs), - elapsedCompilationMs = getCounter(JiterpCounter.ElapsedCompilationMs); + elapsedCompilationMs = getCounter(JiterpCounter.ElapsedCompilationMs), + switchTargetsOk = getCounter(JiterpCounter.SwitchTargetsOk), + switchTargetsFailed = getCounter(JiterpCounter.SwitchTargetsFailed); const backBranchHitRate = (backBranchesEmitted / (backBranchesEmitted + backBranchesNotEmitted)) * 100, tracesRejected = cwraps.mono_jiterp_get_rejected_trace_count(), @@ -1089,8 +1109,8 @@ export function jiterpreter_dump_stats (concise?: boolean): void { mostRecentOptions.directJitCalls ? `direct jit calls: ${directJitCallsCompiled} (${(directJitCallsCompiled / jitCallsCompiled * 100).toFixed(1)}%)` : "direct jit calls: off" ) : ""; - mono_log_info(`// jitted ${bytesGenerated} bytes; ${tracesCompiled} traces (${(tracesCompiled / traceCandidates * 100).toFixed(1)}%) (${tracesRejected} rejected); ${jitCallsCompiled} jit_calls; ${entryWrappersCompiled} interp_entries`); - mono_log_info(`// cknulls eliminated: ${nullChecksEliminatedText}, fused: ${nullChecksFusedText}; back-branches ${backBranchesEmittedText}; ${directJitCallsText}`); + mono_log_info(`// jitted ${bytesGenerated}b; ${tracesCompiled} traces (${(tracesCompiled / traceCandidates * 100).toFixed(1)}%) (${tracesRejected} rejected); ${jitCallsCompiled} jit_calls; ${entryWrappersCompiled} interp_entries`); + mono_log_info(`// cknulls pruned: ${nullChecksEliminatedText}, fused: ${nullChecksFusedText}; back-brs ${backBranchesEmittedText}; switch tgts ${switchTargetsOk}/${switchTargetsFailed + switchTargetsOk}; ${directJitCallsText}`); mono_log_info(`// time: ${elapsedGenerationMs | 0}ms generating, ${elapsedCompilationMs | 0}ms compiling wasm.`); if (concise) return; diff --git a/src/mono/browser/runtime/startup.ts b/src/mono/browser/runtime/startup.ts index 64af593e3cb63..6bc0b69c11882 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/jiterpreter-opcode-values.h b/src/mono/mono/mini/interp/jiterpreter-opcode-values.h index 7d903e2aeefe1..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) @@ -187,6 +188,7 @@ OP(MINT_THROW, ABORT_OUTSIDE_BRANCH_BLOCK_NONE) OP(MINT_MOV_SRC_OFF, NORMAL) OP(MINT_MOV_DST_OFF, NORMAL) +OP(MINT_MONO_MEMORY_BARRIER, NORMAL) OPRANGE(MINT_MONO_EXCHANGE_U1, MINT_MONO_EXCHANGE_I8, HIGH) OPRANGE(MINT_MONO_CMPXCHG_U1, MINT_MONO_CMPXCHG_I8, HIGH) diff --git a/src/mono/mono/mini/interp/jiterpreter.c b/src/mono/mono/mini/interp/jiterpreter.c index 13d337b10c9fe..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 @@ -1165,6 +1177,7 @@ mono_jiterp_stelem_ref ( return 1; } + // keep in sync with jiterpreter-enums.ts JiterpMember enum { JITERP_MEMBER_VT_INITIALIZED = 0, @@ -1256,7 +1269,9 @@ enum { JITERP_COUNTER_BACK_BRANCHES_NOT_EMITTED, JITERP_COUNTER_ELAPSED_GENERATION, JITERP_COUNTER_ELAPSED_COMPILATION, - JITERP_COUNTER_MAX = JITERP_COUNTER_ELAPSED_COMPILATION + JITERP_COUNTER_SWITCH_TARGETS_OK, + JITERP_COUNTER_SWITCH_TARGETS_FAILED, + JITERP_COUNTER_MAX = JITERP_COUNTER_SWITCH_TARGETS_FAILED }; #define JITERP_COUNTER_UNIT 100 diff --git a/src/mono/mono/mini/mini-llvm.c b/src/mono/mono/mini/mini-llvm.c index b52f42a5054e2..aa320d9d9850e 100644 --- a/src/mono/mono/mini/mini-llvm.c +++ b/src/mono/mono/mini/mini-llvm.c @@ -10401,7 +10401,7 @@ MONO_RESTORE_WARNING int stride_len = 32 / cn; int stride_len_2 = stride_len >> 1; int n_strides = 16 / stride_len; - LLVMValueRef swizzle_mask = LLVMConstNull (LLVMVectorType (i8_t, 16)); + LLVMValueRef swizzle_mask = LLVMConstNull (LLVMVectorType (i1_t, 16)); for (int i = 0; i < n_strides; i++) for (int j = 0; j < stride_len; j++) swizzle_mask = LLVMBuildInsertElement (builder, swizzle_mask, const_int8(i * stride_len + ((stride_len_2 + j) % stride_len)), const_int32 (i * stride_len + j), ""); diff --git a/src/mono/mono/utils/options-def.h b/src/mono/mono/utils/options-def.h index fc7e403a2bbd0..ddfc314b6bc7b 100644 --- a/src/mono/mono/utils/options-def.h +++ b/src/mono/mono/utils/options-def.h @@ -89,7 +89,7 @@ DEFINE_BOOL(jiterpreter_jit_call_enabled, "jiterpreter-jit-call-enabled", TRUE, DEFINE_BOOL(wasm_gc_safepoints, "wasm-gc-safepoints", FALSE, "Use GC safepoints on WASM") #else // traces_enabled controls whether the jiterpreter will JIT individual interpreter opcode traces -DEFINE_BOOL_READONLY(jiterpreter_traces_enabled, "jiterpreter-traces-enabled", FALSE, "JIT interpreter opcode traces into WASM") +DEFINE_BOOL(jiterpreter_traces_enabled, "jiterpreter-traces-enabled", TRUE, "JIT interpreter opcode traces into WASM") // interp_entry_enabled controls whether specialized interp_entry wrappers will be jitted DEFINE_BOOL_READONLY(jiterpreter_interp_entry_enabled, "jiterpreter-interp-entry-enabled", FALSE, "JIT specialized WASM interp_entry wrappers") // jit_call_enabled controls whether do_jit_call will use specialized trampolines for hot call sites @@ -177,6 +177,7 @@ DEFINE_INT(jiterpreter_table_size, "jiterpreter-table-size", 6 * 1024, "Size of // FIXME: In the future if we find a way to reduce the number of unique tables we can raise this constant DEFINE_INT(jiterpreter_aot_table_size, "jiterpreter-aot-table-size", 3 * 1024, "Size of the jiterpreter AOT trampoline function tables") DEFINE_INT(jiterpreter_max_module_size, "jiterpreter-max-module-size", 4080, "Size limit for jiterpreter generated WASM modules") +DEFINE_INT(jiterpreter_max_switch_size, "jiterpreter-max-switch-size", 24, "Size limit for jiterpreter switch opcodes (0 to disable)") #endif // HOST_BROWSER #if defined(TARGET_WASM) || defined(TARGET_IOS) || defined(TARGET_TVOS) || defined (TARGET_MACCAT) diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_evp_mac.c b/src/native/libs/System.Security.Cryptography.Native/pal_evp_mac.c index 427c276ee7bde..6927392d91e45 100644 --- a/src/native/libs/System.Security.Cryptography.Native/pal_evp_mac.c +++ b/src/native/libs/System.Security.Cryptography.Native/pal_evp_mac.c @@ -369,32 +369,35 @@ int32_t CryptoNative_EvpMacOneShot(EVP_MAC* mac, params[i] = OSSL_PARAM_construct_end(); + int32_t ret = 0; + if (!EVP_MAC_init(ctx, NULL, 0, params)) { - EVP_MAC_CTX_free(ctx); - return 0; + goto done; } if (!EVP_MAC_update(ctx, data, dataLengthT)) { - EVP_MAC_CTX_free(ctx); - return 0; + goto done; } size_t written = 0; if (!EVP_MAC_final(ctx, destination, &written, macLengthT)) { - EVP_MAC_CTX_free(ctx); - return 0; + goto done; } if (written != macLengthT) { - return -3; + ret = -3; + goto done; } - return 1; + ret = 1; +done: + EVP_MAC_CTX_free(ctx); + return ret; } #else (void)mac; 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/tests/GC/Stress/finalization.config b/src/tests/GC/Stress/finalization.config new file mode 100644 index 0000000000000..89d33a5cd21d7 --- /dev/null +++ b/src/tests/GC/Stress/finalization.config @@ -0,0 +1,36 @@ + + + + + + + + diff --git a/src/tests/GC/Stress/loh.config b/src/tests/GC/Stress/loh.config new file mode 100644 index 0000000000000..268b147071ee7 --- /dev/null +++ b/src/tests/GC/Stress/loh.config @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + diff --git a/src/tests/GC/Stress/non_induced.config b/src/tests/GC/Stress/non_induced.config new file mode 100644 index 0000000000000..7a1aef353e179 --- /dev/null +++ b/src/tests/GC/Stress/non_induced.config @@ -0,0 +1,125 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tests/GC/Stress/poh.config b/src/tests/GC/Stress/poh.config new file mode 100644 index 0000000000000..4bd1d1ca3c374 --- /dev/null +++ b/src/tests/GC/Stress/poh.config @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_106545/Runtime_106545.cs b/src/tests/JIT/Regression/JitBlue/Runtime_106545/Runtime_106545.cs new file mode 100644 index 0000000000000..3212840a85056 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_106545/Runtime_106545.cs @@ -0,0 +1,35 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +/* +Found by Fuzzlyn + +Assertion failed '(emitThisGCrefRegs & regMask) == 0' in 'TestClass:Method4(short,System.Runtime.Intrinsics.Vector512`1[long],byref,short,byref,byref,TestClass+S1,byref):byte:this' during 'Emit code' (IL size 47; hash 0x0a275b75; FullOpts) + + File: D:\a\_work\1\s\src\coreclr\jit\emitxarch.cpp Line: 1498 +*/ +using System; +using System.Runtime.CompilerServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +using Xunit; + +public class Runtime_106545 +{ + Vector512 v512_byte_97 = Vector512.CreateScalar((byte)1); + + public ulong Method0() + { + v512_byte_97 = Vector512.AllBitsSet; + return (0 - Vector512.ExtractMostSignificantBits(v512_byte_97)); + } + + [Fact] + public static void TestEntryPoint() + { + if (Avx2.IsSupported) + { + new Runtime_106545().Method0(); + } + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_106545/Runtime_106545.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_106545/Runtime_106545.csproj new file mode 100644 index 0000000000000..de6d5e08882e8 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_106545/Runtime_106545.csproj @@ -0,0 +1,8 @@ + + + True + + + + + diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_107173/Runtime_107173.cs b/src/tests/JIT/Regression/JitBlue/Runtime_107173/Runtime_107173.cs new file mode 100644 index 0000000000000..147b25e47c49d --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_107173/Runtime_107173.cs @@ -0,0 +1,45 @@ +// 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.4 on 2024-08-26 23:38:13 +// Run on Arm64 Linux +// Seed: 8716802894387291290-vectort,vector64,vector128,armadvsimd,armadvsimdarm64,armaes,armarmbase,armarmbasearm64,armcrc32,armcrc32arm64,armdp,armrdm,armrdmarm64,armsha1,armsha256 +// Reduced from 19.5 KiB to 0.5 KiB in 00:00:27 +// Debug: Outputs <0, 0, 0, 0> +// Release: Outputs <0, 0, 4457472, 0> +using System; +using System.Numerics; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; +using Xunit; + +public class C0 +{ + public ushort F2; + public ushort F8; +} + +public class Runtime_107173 +{ + public static C0 s_8 = new C0(); + + [Fact] + public static void TestLeftShift() + { + if (AdvSimd.IsSupported) + { + var vr6 = s_8.F8; + var vr7 = s_8.F2; + var vr8 = Vector64.Create(vr6, vr7, 0, 0); + Vector128 vr9 = AdvSimd.ShiftLeftLogicalWideningLower(vr8, 0); + Assert.Equal(vr9, Vector128.Zero); + } + } + + [Fact] + public static void TestRightShift() + { + var result = Vector128.AllBitsSet >> 8; + Assert.Equal(result, Vector128.AllBitsSet); + } +} \ No newline at end of file diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_107173/Runtime_107173.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_107173/Runtime_107173.csproj new file mode 100644 index 0000000000000..de6d5e08882e8 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_107173/Runtime_107173.csproj @@ -0,0 +1,8 @@ + + + True + + + + + diff --git a/src/tests/build.proj b/src/tests/build.proj index ee96e154237b6..00ca79e181365 100644 --- a/src/tests/build.proj +++ b/src/tests/build.proj @@ -607,6 +607,7 @@ $(GroupBuildCmd) "/p:ServerGarbageCollection=$(ServerGarbageCollection)" $(GroupBuildCmd) "/p:CLRTestBuildAllTargets=$(CLRTestBuildAllTargets)" $(GroupBuildCmd) "/p:UseCodeFlowEnforcement=$(UseCodeFlowEnforcement)" + $(GroupBuildCmd) "/p:ControlFlowGuard=$(ControlFlowGuard)" $(GroupBuildCmd) "/p:__TestGroupToBuild=$(__TestGroupToBuild)" $(GroupBuildCmd) "/p:__SkipRestorePackages=1" $(GroupBuildCmd) /nodeReuse:false diff --git a/src/tests/ilasm/ilasm_tests.csproj b/src/tests/ilasm/ilasm_tests.csproj index c174bb2a7de62..4bc45cb5a5737 100644 --- a/src/tests/ilasm/ilasm_tests.csproj +++ b/src/tests/ilasm/ilasm_tests.csproj @@ -5,6 +5,8 @@ true true + + true diff --git a/src/tests/issues.targets b/src/tests/issues.targets index 03836f3273397..cb5aa47d386c7 100644 --- a/src/tests/issues.targets +++ b/src/tests/issues.targets @@ -731,9 +731,6 @@ Expectations about finalization order - - Specific to CoreCLR - https://github.com/dotnet/runtimelab/issues/155: SAFEARRAY @@ -1175,6 +1172,13 @@ + + + + https://github.com/dotnet/runtime/issues/107418 + + + diff --git a/src/tests/nativeaot/SmokeTests/HardwareIntrinsics/X64Avx512.csproj b/src/tests/nativeaot/SmokeTests/HardwareIntrinsics/X64Avx512.csproj index d93d939b59749..331f0ed9bca7d 100644 --- a/src/tests/nativeaot/SmokeTests/HardwareIntrinsics/X64Avx512.csproj +++ b/src/tests/nativeaot/SmokeTests/HardwareIntrinsics/X64Avx512.csproj @@ -28,7 +28,7 @@ $(CLRTestBashPreCommands)